【SDOI2011】染色
来源:互联网 发布:网络盒子应用 编辑:程序博客网 时间:2024/04/20 17:55
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Solution
第一眼的水题
这种树上的修改与询问,不是一眼的树链剖分吗!
为了练习动态树,强制性打成了lct。
维护方式
首先肯定要维护颜色段的数量,但是如何转移。
因为lct中左子树的深度小于右子树的深度,那么左子树最深的节点和右子树最浅的节点都会与当前的x相邻,那么我们还需要维护最深的节点和最浅的节点的颜色。
然后转移就很显然了。
Code
#include<iostream>#include<cstdio> #include<cstring>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;const int maxn=100007;int i,j,k,l,n,m,ans,x,y,z;int t[maxn][2],first[maxn*2],next[maxn*2],last[maxn*2],key[maxn];int zuo[maxn],you[maxn],se[maxn],num,pfa[maxn],f[maxn],deep[maxn],lca,jia[maxn];int d[maxn];char s[10];void update(int x){ zuo[x]=(t[x][0])?zuo[t[x][0]]:key[x]; you[x]=(t[x][1])?you[t[x][1]]:key[x]; se[x]=se[t[x][0]]+se[t[x][1]]+1; if(t[x][0]&&you[t[x][0]]==key[x])se[x]--; if(t[x][1]&&zuo[t[x][1]]==key[x])se[x]--;}void add(int x,int y){ last[++num]=y,next[num]=first[x],first[x]=num; last[++num]=x,next[num]=first[y],first[y]=num;}bool son(int x){if(t[f[x]][0]==x)return 0;return 1;}void rotate(int x){ int y=f[x],z=son(x); t[y][z]=t[x][1-z]; if(t[x][1-z])f[t[x][1-z]]=y;f[x]=f[y]; if(f[x])t[f[x]][son(y)]=x;else pfa[x]=pfa[y],pfa[y]=0; t[x][1-z]=y;f[y]=x; update(y),update(x);}void back(int x,int y){ if(!x)return; zuo[x]=you[x]=jia[x]=key[x]=y,se[x]=1;}void down(int x){ if(jia[x]){ back(t[x][0],jia[x]);back(t[x][1],jia[x]); jia[x]=0; }}void remove(int x){ do{ d[++d[0]]=x; x=f[x]; }while(x); while(d[0])down(d[d[0]--]);}void splay(int x){ remove(x); while(f[x]){ if(f[f[x]])if(son(f[x])==son(x))rotate(f[x]);else rotate(x); rotate(x); }}void access(int x){ int y=0; while(x){ splay(x); f[t[x][1]]=0;pfa[t[x][1]]=x; t[x][1]=y;f[y]=x; pfa[y]=0; update(x); y=x,x=pfa[x]; }lca=y;}void build(int x,int y){ access(x);splay(x);pfa[x]=y;}void bfs(int x){ int data[maxn],head=0,tail=1,now,i; bool bz[maxn]; memset(data,0,sizeof(data));memset(bz,0,sizeof(bz)); data[1]=x,bz[x]=1; while(head<tail){ now=data[++head]; rep(i,now){ if(last[i]!=now&&(!bz[last[i]])){ build(last[i],now); data[++tail]=last[i];deep[last[i]]=deep[now]+1; bz[last[i]]=1; } } }}int main(){ // freopen("fan.in","r",stdin); // freopen("fan.out","w",stdout); scanf("%d%d",&n,&m); fo(i,1,n)scanf("%d",&key[i]); fo(i,1,n-1)scanf("%d%d",&k,&l),add(k,l); bfs(1); fo(i,1,m){ scanf("%s%d%d",s,&x,&y); if(s[0]=='C'){ scanf("%d",&z); if(x==y){ splay(x);key[x]=z;continue; } if(deep[x]<deep[y])swap(x,y); access(x);access(y);splay(x); key[lca]=z; back(x,z);back(t[lca][1],z); update(lca); } else{ if(x==y){ printf("1\n");continue; } if(deep[x]<deep[y])swap(x,y); access(x);access(y);splay(x); ans=se[x]+se[t[lca][1]]+1; if(zuo[x]==key[lca])ans--; if(key[lca]==zuo[t[lca][1]])ans--; printf("%d\n",ans); } }}
1 0
- [SDOI2011]染色
- 【SDOI2011】染色
- 【SDOI2011】染色
- 【SDOI2011】染色
- SDOI2011 染色
- 染色 SDOI2011
- [SDOI2011]染色
- 【BZOJ - 2243】 SDOI2011 染色
- [Bzoj2243][SDOI2011]染色
- BZOJ 2243: [SDOI2011]染色
- bzoj2243: [SDOI2011]染色 树链剖分
- 【BZOJ2243】[SDOI2011]染色 树链剖分
- 【BZOJ2243】【SDOI2011】染色 树链剖分
- 【BZOJ 2243】 [SDOI2011]染色
- bzoj 2243: [SDOI2011]染色
- 【SDOI2011】【BZOJ2243】【树链剖分】染色
- 【bzoj2243】【sdoi2011】染色【树链剖分】
- bzoj2243: [SDOI2011]染色
- OpenGl的glMatrixMode函数理解
- libev 学习笔记之timer实现原理
- C语言中的static函数
- 安卓学习之—自定义Dialog
- 杂乱总结
- 【SDOI2011】染色
- 1012. The Best Rank (25)
- session序列化异常、session的销毁方式
- Design Support Library第三部分:Snackbar样式
- oracle分页语句和随机取N条记录
- 1003. Emergency
- 欢迎使用CSDN-markdown编辑器
- Android颜色对照
- cPP别名