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]旅行(树链剖分+线段树)相关推荐

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1153  Solved: 421 [Submit][Sta ...

  2. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  3. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  4. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  5. 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 ...

  6. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  7. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  8. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  9. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  10. YbtOJ-染色计划【树链剖分,线段树,tarjan】

    正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai​,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...

最新文章

  1. JS动态生成的元素,其对应的方法不响应(比如单击事件,鼠标移动事件等)...
  2. 【线段树】【FeyatCup】——2.法法塔的奖励
  3. mongoDB - 日常操作四
  4. crossplatform---Nodejs in Visual Studio Code 01.简单介绍Nodejs
  5. jdbc thin连接oracle10,setSavepoint方法报错解决办法
  6. 计算机无法创建新文件夹,无法创建文件,教您无法新建文件夹怎么办
  7. 上手 Docker 容器,不应该是个问题
  8. [转]短篇小说《来》
  9. Java的一个关于“星球”的枚举
  10. 读取GY-951模块数据(Linux)
  11. tcpdump抓包工具各参数详解
  12. 金山词霸2006打开没有响应怎办?
  13. Foxmail的创建
  14. python接外包_程序员到底要不要接外包?
  15. 中科院计算机所沈阳待遇怎么样,中科院沈阳计算技术研究所计算机技术怎么样...
  16. 西电计算机学院通知,西安电子科技大学计算机科学与技术学院关于发放2020级硕士研究生正式录取通知书的通知...
  17. 上车了!AR摩托车头盔了解一下?
  18. Objective C范型
  19. 慕课学习史上最全零基础入门HTML5和CSS笔记
  20. 2021年10月-精品总结汇报PPT模板-15套

热门文章

  1. Atitit 组织软资产建设 知识管理 经济学架构体系
  2. paip.编程语言方法重载实现的原理及python,php,js中实现方法重载
  3. paip.提升性能--多核cpu中的java/.net/php/c++编程
  4. 2021年度 Egon Balas 奖得主:达摩院印卧涛
  5. 阿里云祝顺民:云网络心智大图解读 | 云栖大会
  6. 蚂蚁可信原生负责人入选“2021年度全球青年领袖”名单
  7. 从数据治理、数据资产管理,到数据中台的落地实战!
  8. android 延时摄影,当「延时摄影」和「镜头慢放」结合,手机视频从未有如此质感……#Android&iOS...
  9. 毕设题目:Matlab图像修复
  10. 【优化预测】基于matlab布谷鸟算法优化灰色模型预测【含Matlab源码 1244期】