1 条题解
-
0
自动搬运
来自洛谷,原作者为

jerry3128
Astill System搬运于
2025-08-24 22:11:43,当前版本为作者最后更新于2021-07-09 16:40:24,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
【Ynoi2012】 梦断 SCOI2017
题目大意:
- 有一颗静态树,一共有 30 种颜色,每次会单点或者同色块修改颜色。
- 询问:
- 某个节点的颜色。
- 这个节点的同色块的大小。
- 这个节点同色块的深度最大值和最小值。
题解:splay & 括号序。
- 我们考虑对于每一个节点维护每一种不同于自己颜色的儿子的 ETT ,如果一个节点的颜色与父亲相同,那么这个节点应与父亲在同一颗 ETT 当中。即我们用 ETT 森林维护每一个同色连通块。如果两个连通块有相同的颜色和父亲并且颜色不同于父亲,那么显然他们可以简单地收尾相接将二者合并。并维护出链接异色节点的父子边,把标记打在父亲上。
- 那么找到一个块的信息就是在 ETT 上直接 splay 后得到的信息。异色块的信息都被专门维护的异色边隔离开。一个 ETT 上的根就是一个同色连通块的根。
- 考虑操作一,如果对单点颜色进行修改。那么我们考虑信息变更的部分:
- 它与父亲的关系:可能从父亲的 ETT 中被挖出来,也可能被放入父亲的 ETT 中。
- 它与儿子的关系:当前 ETT 子树区间的所有儿子都会变成异色的,同时可能会有本来异色的儿子变为同色的。因为在刚刚我们将颜色相同且父亲相同的儿子的 ETT 收尾相接,所以可以直接把整个 splay 挂在当前的点的括号序之间。
- 考虑操作二,对块颜色进行修改,那么就是整个 ETT 被带着跑。考虑信息改变部分。
- 它的块根与父亲的关系:可能整颗 ETT 被放入块根父亲的括号序之间,或者什么也没有。
- 整个块向外连出的异色边:有可能修改的目标颜色会涉及多个异色边。
- 前者很好维护,后者我们看所谓的“异色边”的本质。先把“异色边”新定义放这:每个节点向某个异色亲儿子点集的连边。(一个集合算一条)
- 因为我们将颜色、父亲相同的块根的 ETT 相接,因此可以直接集合操作。即异色边的本质应该是:每个节点的亲儿子当中不同于当前节点颜色的种数,处于 ,再看异色边的变化,每次操作一最多增加 2 的异色边,分别为操作节点的父亲与操作节点当前同色的儿子。操作二会遍历一颗 ETT 来找到将删除的异色边,因为用了平衡树作为维护 ETT 的东西,所以找到一个节点的复杂度是均摊 的,每个节点对于一种颜色最多只有一条异色边。所以复杂度是均摊 减少一条“异色边”。全局均摊复杂度是完全能够接受的。
//ayame保佑,夸哥保佑,狗妈保佑,MDR保佑,锉刀怪保佑,M99保佑,克爹保佑 #include<bits/stdc++.h> using namespace std; int p1=1000000,p2=0; char buf[1000005],wb[1000005]; int gc() { if(p1>=1000000)fread(buf,1,1000000,stdin),p1=0; return buf[p1++]; } #define gc getchar #define Loli true #define Kon xor true long long getint() { long long ret=0,flag=1; char c=gc(); while(c<'0'||c>'9') { if(c=='-')flag=-1; c=gc(); } while(c<='9'&&c>='0') { ret=(ret<<3)+(ret<<1)+c-'0'; c=gc(); } return ret*flag; } void pc(char x) { if(p2>=1000000)fwrite(wb,1,1000000,stdout),p2=0; wb[p2++]=x; } void wrt(long long x) { if(x<0)pc('-'),x=-x; int c[24]= {0}; if(!x)return pc('0'),void(); while(x)c[++c[0]]=x%10,x/=10; while(c[0])pc(c[c[0]--]+'0'); } int n,m,a[100005]; int fa[100005],dep[100005]; int o[100005][31],prt[20][100005]; namespace ETT { struct node { int ch[2],fa,pre,suf; int vl,sz,dep,mx,mi,etag,stag; int col,ctag; } v[200005]; void push_down(int rt) { if(v[rt].ctag) { if(v[rt].ch[0])v[v[rt].ch[0]].ctag=v[v[rt].ch[0]].col=v[rt].ctag; if(v[rt].ch[1])v[v[rt].ch[1]].ctag=v[v[rt].ch[1]].col=v[rt].ctag; v[rt].ctag=0; } } void push_up(int rt) { v[rt].pre=v[rt].suf=rt; v[rt].mx=v[rt].mi=v[rt].dep; if(v[rt].ch[0])v[rt].pre=v[v[rt].ch[0]].pre,v[rt].mx=max(v[rt].mx,v[v[rt].ch[0]].mx),v[rt].mi=min(v[rt].mi,v[v[rt].ch[0]].mi); if(v[rt].ch[1])v[rt].suf=v[v[rt].ch[1]].suf,v[rt].mx=max(v[rt].mx,v[v[rt].ch[1]].mx),v[rt].mi=min(v[rt].mi,v[v[rt].ch[1]].mi); v[rt].stag=v[rt].etag|v[v[rt].ch[0]].stag|v[v[rt].ch[1]].stag; v[rt].sz=v[v[rt].ch[0]].sz+v[rt].vl+v[v[rt].ch[1]].sz; } void rot(int x) { int p=v[x].fa,g=v[p].fa; bool d=v[p].ch[1]==x; if(g)v[g].ch[v[g].ch[1]==p]=x; v[p].ch[d]=v[x].ch[d^1]; v[v[x].ch[d^1]].fa=p; v[x].ch[d^1]=p; v[x].fa=g,v[p].fa=x; push_up(p),push_up(x); } void pre_push_down(int rt) { if(v[rt].fa)pre_push_down(v[rt].fa); push_down(rt); } void splay(int x,int f=0) { if(!x)return; pre_push_down(x); while(v[x].fa!=f) { int p=v[x].fa,g=v[p].fa; if(g!=f)rot(v[g].ch[0]==p^v[p].ch[0]==x?x:p); rot(x); } } void init() { for(int i=1; i<=n; i++) { v[i<<1].vl=1,v[i<<1].ch[1]=i<<1|1,v[i<<1|1].fa=i<<1,v[i<<1].col=a[i]; v[i<<1].dep=v[i<<1|1].dep=dep[i],push_up(i<<1|1),push_up(i<<1); } } int merge_bro(int x,int y) { if(!x||!y)return x|y; splay(x),splay(y); int d=v[x].suf; splay(d),v[d].ch[1]=y,v[y].fa=d,push_up(d); return x; } void merge_prt(int x,int y) { splay(x<<1),splay(v[v[x<<1].ch[1]].pre,x<<1),splay(y); v[v[x<<1].ch[1]].ch[0]=y,v[y].fa=v[x<<1].ch[1],push_up(v[x<<1].ch[1]),push_up(x<<1); } int ask(int x) { if(x==0)return x; return splay(x),v[x].pre; } void dfs(int x,int c,vector<int>&vec) { push_down(x); if(v[x].etag>>c&1)vec.push_back(x>>1),v[x].etag^=1<<c; if(v[v[x].ch[0]].stag>>c&1)dfs(v[x].ch[0],c,vec); if(v[v[x].ch[1]].stag>>c&1)dfs(v[x].ch[1],c,vec); push_up(x); } } void ask(int x) { int p=x; for(int i=19; i>=0; i--)if(ETT::ask(p<<1)==ETT::ask(prt[i][p]<<1))p=prt[i][p]; ETT::splay(p<<1),ETT::splay(p<<1|1,p<<1); int sz=ETT::v[ETT::v[p<<1|1].ch[0]].sz+1,len=max(ETT::v[ETT::v[p<<1|1].ch[0]].mx-dep[p],0)+1; wrt(ETT::v[p<<1].col),pc(' '),wrt(sz),pc(' '),wrt(len),pc('\n'); } void paint_point(int x,int gc) { int p=x; for(int i=19; i>=0; i--)if(ETT::ask(p<<1)==ETT::ask(prt[i][p]<<1))p=prt[i][p]; ETT::splay(x<<1),ETT::splay(x<<1|1,x<<1); int l=ETT::v[x<<1].ch[0],r=ETT::v[x<<1|1].ch[1],col=ETT::v[x<<1].col; ETT::v[l].fa=0,ETT::v[r].fa=0,ETT::v[x<<1].ch[0]=0,ETT::v[x<<1|1].ch[1]=0; ETT::push_up(x<<1|1),ETT::push_up(x<<1); if(fa[x]) { int tmp=ETT::merge_bro(l,r); o[fa[p]][col]=tmp; ETT::splay(fa[p]<<1); if(!o[fa[p]][col])ETT::v[fa[p]<<1].etag^=1<<col; ETT::push_up(fa[p]<<1); } else ETT::merge_bro(l,r); if(ETT::v[x<<1|1].ch[0]) { int d=ETT::v[x<<1|1].ch[0]; ETT::v[d].fa=0,ETT::v[x<<1|1].ch[0]=0; ETT::push_up(x<<1|1),ETT::push_up(x<<1); o[x][col]=d,ETT::v[x<<1].etag|=1<<col,ETT::push_up(x<<1); } ETT::v[x<<1].col=ETT::v[x<<1|1].col=gc; if(o[x][gc]) { int d=o[x][gc]; o[x][gc]=0,ETT::splay(d),ETT::v[x<<1|1].ch[0]=d,ETT::v[d].fa=x<<1|1; ETT::v[x<<1].etag^=1<<gc,ETT::push_up(x<<1|1),ETT::push_up(x<<1); } if(fa[x]) { ETT::splay(fa[x]<<1); if(gc!=ETT::v[fa[x]<<1].col) { o[fa[x]][gc]=ETT::merge_bro(o[fa[x]][gc],x<<1); ETT::splay(fa[x]<<1); ETT::v[fa[x]<<1].etag|=1<<gc; ETT::push_up(fa[x]<<1); } else ETT::merge_prt(fa[x],x<<1); } } void paint_block(int x,int gc) { for(int i=19; i>=0; i--)if(ETT::ask(x<<1)==ETT::ask(prt[i][x]<<1))x=prt[i][x]; ETT::splay(x<<1),ETT::splay(x<<1|1,x<<1); int l=ETT::v[x<<1].ch[0],r=ETT::v[x<<1|1].ch[1],col=ETT::v[x<<1].col; ETT::v[l].fa=0,ETT::v[r].fa=0,ETT::v[x<<1].ch[0]=0,ETT::v[x<<1|1].ch[1]=0; ETT::push_up(x<<1|1),ETT::push_up(x<<1); if(fa[x]) { o[fa[x]][col]=ETT::merge_bro(l,r); ETT::splay(fa[x]<<1); if(!o[fa[x]][col])ETT::v[fa[x]<<1].etag^=1<<col; ETT::push_up(fa[x]<<1); } else ETT::merge_bro(l,r); ETT::v[x<<1].col=ETT::v[x<<1].ctag=gc; vector<int> vec; ETT::dfs(x<<1,gc,vec); for(int w:vec)ETT::merge_prt(w,o[w][gc]),o[w][gc]=0; if(fa[x]) { ETT::splay(fa[x]<<1); if(gc!=ETT::v[fa[x]<<1].col) { o[fa[x]][gc]=ETT::merge_bro(o[fa[x]][gc],x<<1); ETT::splay(fa[x]<<1); ETT::v[fa[x]<<1].etag|=1<<gc; ETT::push_up(fa[x]<<1); } else ETT::merge_prt(fa[x],x<<1); } } int main() { n=getint(); for(int i=1; i<=n; i++)prt[0][i]=fa[i]=getint(),dep[i]=dep[fa[i]]+1; for(int j=1; j<20; j++) for(int i=1; i<=n; i++)prt[j][i]=prt[j-1][prt[j-1][i]]; for(int i=1; i<=n; i++)a[i]=getint(); ETT::init(),m=getint(); for(int i=n; i>=2; i--) { if(a[fa[i]]==a[i])ETT::merge_prt(fa[i],i<<1); else o[fa[i]][a[i]]=ETT::merge_bro(o[fa[i]][a[i]],i<<1),ETT::splay(fa[i]<<1),ETT::v[fa[i]<<1].etag|=1<<a[i],ETT::push_up(fa[i]<<1); } for(int i=1; i<=m; i++) { int opt=getint(); if(opt==1) { int x=getint(),c=getint(); paint_point(x,c); } if(opt==2) { int x=getint(),c=getint(); paint_block(x,c); } if(opt==3)ask(getint()); } fwrite(wb,1,p2,stdout); return Loli Kon; }
- 1
信息
- ID
- 4298
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者