[BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)
Description
S国有N个城市,编号从1到N。城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市。每个城市信仰不同的宗教,如飞天面条神教、隐形独角兽教、绝地教都是常见的信仰。为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行。旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿。当然旅程的终点也是信仰与他相同的城市。S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值。
在S国的历史上常会发生以下几种事件:
”CC x c”:城市x的居民全体改信了c教;
”CW x w”:城市x的评级调整为w;
”QS x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过的城市的评级总和;
”QM x y”:一位旅行者从城市x出发,到城市y,并记下了途中留宿过
的城市的评级最大值。
由于年代久远,旅行者记下的数字已经遗失了,但记录开始之前每座城市的信仰与评级,还有事件记录本身是完好的。请根据这些信息,还原旅行者记下的数字。 为了方便,我们认为事件之间的间隔足够长,以致在任意一次旅行中,所有城市的评级和信仰保持不变。
Solution
只需要对每个宗教建一棵线段树就好啦
#include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #define MAXN 100005 using namespace std; int n,q,w[MAXN],c[MAXN],head[MAXN],cnt=0; int father[MAXN],top[MAXN],maxv[MAXN],siz[MAXN],deep[MAXN],pos[MAXN],sz=0; int tot=0,rt[MAXN],ls[MAXN*100],rs[MAXN*100],maxn[MAXN*100],sum[MAXN*100]; int read() {int x=0,f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } struct Node1 {int next,to; }Edges[MAXN*2]; void addedge(int u,int v) {Edges[++cnt].next=head[u];head[u]=cnt;Edges[cnt].to=v; } void dfs1(int u) {siz[u]=1;for(int i=head[u];~i;i=Edges[i].next){int v=Edges[i].to;if(v==father[u])continue;father[v]=u,deep[v]=deep[u]+1;dfs1(v);siz[u]+=siz[v];if(siz[v]>siz[maxv[u]])maxv[u]=v;} } void dfs2(int u,int t) {top[u]=t;++sz,pos[u]=sz;if(maxv[u])dfs2(maxv[u],t);for(int i=head[u];~i;i=Edges[i].next){int v=Edges[i].to;if(v==maxv[u]||v==father[u])continue;dfs2(v,v);} } void update(int idx) {sum[idx]=sum[ls[idx]]+sum[rs[idx]];maxn[idx]=max(maxn[ls[idx]],maxn[rs[idx]]); } void change(int &idx,int l,int r,int p,int w) {if(!idx)++tot,idx=tot;if(l==r){maxn[idx]=sum[idx]=w;return;}int mid=(l+r)>>1;if(p<=mid)change(ls[idx],l,mid,p,w);else change(rs[idx],mid+1,r,p,w);update(idx); } int querysum(int idx,int l,int r,int L,int R) {if(!idx)return 0;if(L==l&&R==r)return sum[idx];int mid=(l+r)>>1;if(R<=mid)return querysum(ls[idx],l,mid,L,R);else if(L>mid)return querysum(rs[idx],mid+1,r,L,R);else return querysum(ls[idx],l,mid,L,mid)+querysum(rs[idx],mid+1,r,mid+1,R); } int querymax(int idx,int l,int r,int L,int R) {if(!idx)return 0;if(L==l&&R==r)return maxn[idx];int mid=(l+r)>>1;if(R<=mid)return querymax(ls[idx],l,mid,L,R);else if(L>mid)return querymax(rs[idx],mid+1,r,L,R);else return max(querymax(ls[idx],l,mid,L,mid),querymax(rs[idx],mid+1,r,mid+1,R)); } int QS(int x,int y) {int t=c[x],res=0;while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);res+=querysum(rt[t],1,sz,pos[top[x]],pos[x]);x=father[top[x]];}if(deep[x]<deep[y])swap(x,y);res+=querysum(rt[t],1,sz,pos[y],pos[x]);return res; }int QM(int x,int y) {int t=c[x],res=0;while(top[x]!=top[y]){if(deep[top[x]]<deep[top[y]])swap(x,y);res=max(res,querymax(rt[t],1,sz,pos[top[x]],pos[x]));x=father[top[x]];}if(deep[x]<deep[y])swap(x,y);res=max(res,querymax(rt[t],1,sz,pos[y],pos[x]));return res; } int main() {memset(head,-1,sizeof(head));n=read(),q=read();for(int i=1;i<=n;i++)w[i]=read(),c[i]=read();for(int i=1;i<n;i++){int x=read(),y=read();addedge(x,y),addedge(y,x);}deep[1]=1;dfs1(1),dfs2(1,1);for(int i=1;i<=n;i++)change(rt[c[i]],1,sz,pos[i],w[i]);for(int i=1;i<=q;i++){char opt[5];scanf("%s",opt);int x=read(),y=read();if(opt[1]=='C'){change(rt[c[x]],1,sz,pos[x],0);change(rt[y],1,sz,pos[x],w[x]);c[x]=y;}else if(opt[1]=='W'){change(rt[c[x]],1,sz,pos[x],y);w[x]=y;}else if(opt[1]=='S')printf("%d\n",QS(x,y));else printf("%d\n",QM(x,y));}return 0; }
转载于:https://www.cnblogs.com/Zars19/p/6937529.html
[BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)相关推荐
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MB Submit: 1153 Solved: 421 [Submit][Sta ...
- BZOJ3862Little Devil I——树链剖分+线段树
题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...
- CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)
题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...
- CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)
题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...
- P2486 [SDOI2011]染色(树链剖分+线段树)
题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...
- BZOJ4127Abs——树链剖分+线段树
题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- YbtOJ-染色计划【树链剖分,线段树,tarjan】
正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...
最新文章
- JS动态生成的元素,其对应的方法不响应(比如单击事件,鼠标移动事件等)...
- 【线段树】【FeyatCup】——2.法法塔的奖励
- mongoDB - 日常操作四
- crossplatform---Nodejs in Visual Studio Code 01.简单介绍Nodejs
- jdbc thin连接oracle10,setSavepoint方法报错解决办法
- 计算机无法创建新文件夹,无法创建文件,教您无法新建文件夹怎么办
- 上手 Docker 容器,不应该是个问题
- [转]短篇小说《来》
- Java的一个关于“星球”的枚举
- 读取GY-951模块数据(Linux)
- tcpdump抓包工具各参数详解
- 金山词霸2006打开没有响应怎办?
- Foxmail的创建
- python接外包_程序员到底要不要接外包?
- 中科院计算机所沈阳待遇怎么样,中科院沈阳计算技术研究所计算机技术怎么样...
- 西电计算机学院通知,西安电子科技大学计算机科学与技术学院关于发放2020级硕士研究生正式录取通知书的通知...
- 上车了!AR摩托车头盔了解一下?
- Objective C范型
- 慕课学习史上最全零基础入门HTML5和CSS笔记
- 2021年10月-精品总结汇报PPT模板-15套
热门文章
- Atitit 组织软资产建设 知识管理 经济学架构体系
- paip.编程语言方法重载实现的原理及python,php,js中实现方法重载
- paip.提升性能--多核cpu中的java/.net/php/c++编程
- 2021年度 Egon Balas 奖得主:达摩院印卧涛
- 阿里云祝顺民:云网络心智大图解读 | 云栖大会
- 蚂蚁可信原生负责人入选“2021年度全球青年领袖”名单
- 从数据治理、数据资产管理,到数据中台的落地实战!
- android 延时摄影,当「延时摄影」和「镜头慢放」结合,手机视频从未有如此质感……#Android&iOS...
- 毕设题目:Matlab图像修复
- 【优化预测】基于matlab布谷鸟算法优化灰色模型预测【含Matlab源码 1244期】