【Bzoj3531】旅行
来源:互联网 发布:按键精灵文字输出源码 编辑:程序博客网 时间:2024/06/10 20:20
题意:有n个城市,每个城市有权值和颜色,支持的操作有单点修改权值,单点修改颜色,查询区间同颜色之和,查询区间同颜色最大值。
思路:对于每种颜色,放入不同的线段树,但其实整个加起来还是还是n个结点,值得注意的是,这里要使用动态开点,要一步步记录左右儿子的编号,而不能使用2i,2i+1直接去找,而这样建树的话,就可以很方便的查询同颜色的结点了,修改操作啥的把原颜色中的结点改为0,再在现在的颜色中开点就可以了。
#include <cstdio>#include <algorithm>#define Rep(i,s,t) for(int i=s;i<=t;i++)#define For(i,s,t) for(int i=s;i;i=t)using namespace std;const int maxx = 100000 + 25;const int maxm = 4000000 + 25;const int Inf = (unsigned)(-1) >> 1;int head[maxx],nxt[maxx<<1],to[maxx<<1],a[maxx],c[maxx];int top[maxx],rnk[maxx],size[maxx],dpt[maxx],ftr[maxx],son[maxx];int T[maxm],Tmax[maxm],lc[maxm],rc[maxm],rt[maxx];int num,cnt,tot,n,m,x,y,k;char f[8];namespace Y{ void Ins(int x,int y) {to[++num]=y;nxt[num]=head[x];head[x]=num;} void Dfs1(int x){ size[x] = 1; For( i , head[x] , nxt[i] ){ int now = to[i];if(now == ftr[x]) continue; dpt[now] = dpt[x] + 1;ftr[now] = x; Dfs1(now);size[x] += size[now]; if(size[now] > size[son[x]]) son[x] = now; } } void Dfs2(int x,int brn){ rnk[x] = ++cnt;top[x] = brn; if(son[x]) Dfs2(son[x],brn); For( i , head[x] , nxt[i] ) if(to[i] != ftr[x] && to[i] != son[x]) Dfs2(to[i],to[i]); } void upt(int i){ T[i] = T[lc[i]] + T[rc[i]]; Tmax[i] = max(Tmax[lc[i]],Tmax[rc[i]]); } void modify(int &i,int pos,int l,int r,int k){ if(!i) i = ++tot;if(l == r) {T[i] = Tmax[i] = k;return;} int mid = (l+r) >> 1; if(pos <= mid) modify(lc[i],pos,l,mid,k); if(pos > mid) modify(rc[i],pos,mid+1,r,k); upt(i); } void chk(int &tmp,int pls,int flag){ if(flag == 0) tmp = tmp + pls; if(flag == 1) tmp = max(tmp,pls); } int Query(int i,int x,int y,int l,int r,int flag){ if(x <= l && r <= y) return flag? Tmax[i] : T[i]; int ans = (flag)? -Inf : 0;int mid = (l+r) >> 1; if(x <= mid) chk(ans,Query(lc[i],x,y,l,mid,flag),flag); if(y > mid) chk(ans,Query(rc[i],x,y,mid+1,r,flag),flag); return ans; } int Get(int i,int x,int y,int flag){ int ans = (flag)? -Inf : 0; while(top[x] != top[y]){ if(dpt[top[x]] > dpt[top[y]]) x^=y^=x^=y; chk(ans,Query(i,rnk[top[y]],rnk[y],1,n,flag),flag); y = ftr[top[y]]; } if(rnk[x] > rnk[y]) x^=y^=x^=y; chk(ans,Query(i,rnk[x],rnk[y],1,n,flag),flag); return ans; } }using namespace Y;int main(){ scanf("%d%d",&n,&m); Rep( i , 1 , n ) scanf("%d%d",&a[i],&c[i]); Rep( i , 1 , n-1 ) scanf("%d%d",&x,&y),Ins(x,y),Ins(y,x); Dfs1(1),Dfs2(1,1);Rep( i , 1 , n ) modify(rt[c[i]],rnk[i],1,n,a[i]); while( m-- ){ scanf("%s",f); if(f[1] == 'S') scanf("%d%d",&x,&y),printf("%d\n",Get(rt[c[x]],x,y,0)); if(f[1] == 'C'){ scanf("%d%d",&x,&y); modify(rt[c[x]],rnk[x],1,n,0); c[x]=y; modify(rt[c[x]],rnk[x],1,n,a[x]); } if(f[1] == 'W') scanf("%d%d",&x,&y),a[x]=y,modify(rt[c[x]],rnk[x],1,n,a[x]); if(f[1] == 'M') scanf("%d%d",&x,&y),printf("%d\n",Get(rt[c[x]],x,y,1)); } return 0;}
0 0
- BZOJ3531旅行
- 【Bzoj3531】旅行
- [BZOJ3531]旅行
- BZOJ3531 [Sdoi2014]旅行
- 【BZOJ3531】【Sdoi2014】旅行 树链剖分。
- [BZOJ3531]SDOI2014旅行
- 【SDOI2014】【BZOJ3531】旅行
- bzoj3531【SDOI2014】旅行
- [BZOJ3531] [SDOI2014] 旅行
- [bzoj3531][SDOI2014]旅行
- BZOJ3531 【Sdoi2014】旅行
- bzoj3531: [Sdoi2014]旅行
- bzoj3531: [Sdoi2014]旅行
- BZOJ3531 旅行 树链剖分
- 【bzoj3531】[SDOI2014]旅行
- 【bzoj3531】[Sdoi2014]旅行
- 【bzoj3531】[Sdoi2014]旅行
- [bzoj3531][Sdoi2014]旅行 树链剖分
- Linux中Idea的安装
- #Vi,java,Ant,Junit学习笔记
- if-else与if-esle if...的详解
- ubuntu16.04上搭建git服务器
- C代码规范
- 【Bzoj3531】旅行
- Android面试题笔记(二)
- TensorFlow 学习(九)—— 初始化函数(概率分布函数 api、常数生成函数)
- python基础原理
- C++游戏服务器的性能优化
- 题目1029:魔咒词典
- RequestMapping注解
- MySql_添加索引
- Android 常用的设计模式