[SDOI2017]树点涂色

树点涂色

题目链接:https://www.luogu.org/problemnew/show/P3703

lct

  可以发现这题与lct的操作十分相似

  颜色相同就在同一个splay里面

  操作1:就是lct的access操作

  操作2:co[u]表示u到根节点的颜色总数

    ans=co[u]+co[v]-2*co[lca]+1,其实就是u节点到lca之前的颜色数+v节点到lca之前的颜色数+lca的颜色

  操作3:查询一颗子树,可以考虑用dfs序+线段树维护子树的最大值

    查询就正常的区间查询

    当操作1修改时,access将轻边变成重边时,原来重边的子树多了一种颜色,区间+1

                          现在重边的子树少了一种颜色,区间-1

代码

  

  1 #include<iostream>
  2 #include<cstdio>
  3 using namespace std;
  4 const int M=1e5+9;
  5 int n,m,num=0,id=0,df=0;
  6 int L[M<<1],pw[23];
  7 int head[M],fir[M],dep[M],d[M<<1][23];struct P{int to,ne;}e[M<<1];
  8 int tid[M],pid[M],last[M],f[M],c[M][2];
  9 int Ma[M<<2],vi[M<<2];
 10 inline int read(){
 11     int rex=0,f=1;char ch=getchar();
 12     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 13     while(ch>='0'&&ch<='9'){rex=rex*10+ch-'0';ch=getchar();}
 14     return rex*f;
 15 }
 16 void dfs(int u,int fa){
 17     f[u]=fa;pid[tid[u]=++id]=u;dep[u]=dep[fa]+1;d[fir[u]=++df][0]=u;
 18     for(int i=head[u];i;i=e[i].ne){
 19         int v=e[i].to;
 20         if(v!=fa){dfs(v,u);d[++df][0]=u;}
 21     }
 22     last[u]=id;
 23 }
 24 inline int Min(int x,int y){
 25     return dep[x]<dep[y]?x:y;
 26 }
 27 inline int ask(int l,int r){
 28     l=fir[l],r=fir[r];
 29     if(l>r)swap(l,r);
 30     int k=L[r-l+1];
 31     return Min(d[l][k],d[r-pw[k]+1][k]);
 32 }
 33 void build(int now,int l,int r){
 34     if(l==r){Ma[now]=dep[pid[l]];return;}
 35     int mid=(l+r)>>1;
 36     build(now<<1,l,mid);
 37     build(now<<1|1,mid+1,r);
 38     Ma[now]=max(Ma[now<<1],Ma[now<<1|1]);
 39 }
 40 void pushdown(int now,int l,int r){
 41     if(vi[now]){
 42         Ma[now]+=vi[now];
 43         if(l<r)vi[now<<1]+=vi[now];
 44         if(l<r)vi[now<<1|1]+=vi[now];
 45         vi[now]=0;
 46     }
 47 }
 48 void pushup(int now,int l,int r){
 49     if(l==r)return;
 50     int mid=(l+r)>>1;
 51     pushdown(now<<1,l,mid);
 52     pushdown(now<<1|1,mid+1,r);
 53     Ma[now]=max(Ma[now<<1],Ma[now<<1|1]);
 54 }
 55 void update(int now,int l,int r,int x,int y,int p){
 56     pushdown(now,l,r);
 57     if(x<=l&&r<=y){vi[now]+=p;return;}
 58     int mid=(l+r)>>1;
 59     if(x<=mid)update(now<<1,l,mid,x,y,p);
 60     if(y>mid)update(now<<1|1,mid+1,r,x,y,p);
 61     pushup(now,l,r);
 62 }
 63 int query(int now,int l,int r,int x,int y){
 64     pushdown(now,l,r);
 65     if(x<=l&&r<=y)return Ma[now];
 66     int mid=(l+r)>>1,ans=0;
 67     if(x<=mid)ans=max(ans,query(now<<1,l,mid,x,y));
 68     if(y>mid)ans=max(ans,query(now<<1|1,mid+1,r,x,y));
 69     return ans;
 70 }
 71 bool isroot(int x){
 72     return c[f[x]][0]!=x&&c[f[x]][1]!=x;
 73 }
 74 void rotate(int x){
 75     int y=f[x],z=f[y],k=c[y][1]==x,ch=c[x][k^1];
 76     if(!isroot(y))c[z][c[z][1]==y]=x;f[x]=z;
 77     c[y][k]=ch;f[ch]=y;
 78     c[x][k^1]=y;f[y]=x;
 79 }
 80 void splay(int x){
 81     for(int y=f[x];!isroot(x);y=f[x]){
 82         if(!isroot(y))
 83             rotate(((c[f[y]][1]==y)==(c[x][1]==x))?y:x);
 84         rotate(x);
 85     }
 86 }
 87 void access(int x){
 88     for(int t=0,s;x;t=x,x=f[x]){
 89         splay(x);
 90         if(s=c[x][1]){
 91             while(c[s][0])s=c[s][0];
 92             update(1,1,n,tid[s],last[s],1);
 93         }
 94         if(c[x][1]=t){
 95             while(c[t][0])t=c[t][0];
 96             update(1,1,n,tid[t],last[t],-1);
 97         }
 98     }
 99 }
100 int main(){
101     n=read(),m=read();
102     for(int i=1,u,v;i<n;++i){
103         u=read(),v=read();
104         e[++num]=(P){v,head[u]};head[u]=num;
105         e[++num]=(P){u,head[v]};head[v]=num;
106     }
107     dfs(1,0);
108     L[1]=0;pw[0]=1;
109     for(int i=1;i<=19;++i)pw[i]=pw[i-1]<<1;
110     for(int i=2;i<=df;++i)L[i]=L[i>>1]+1;
111     for(int j=1;j<=19;++j){
112         for(int i=1;i+pw[j]-1<=df;++i){
113             d[i][j]=Min(d[i][j-1],d[i+pw[j-1]][j-1]);
114         }
115     }
116     build(1,1,n);
117     for(int i=1,o,x,y,lc;i<=m;++i){
118         o=read(),x=read();
119         if(o==1)access(x);
120         if(o==2){
121             y=read();lc=ask(x,y);
122             x=query(1,1,n,tid[x],tid[x]);
123             y=query(1,1,n,tid[y],tid[y]);
124             lc=query(1,1,n,tid[lc],tid[lc]);
125             printf("%d\n",x+y-lc*2+1);
126         }
127         if(o==3)printf("%d\n",query(1,1,n,tid[x],last[x]));
128     }
129     return 0;
130 }
View Code

 

posted @ 2018-11-27 22:43  sjie  阅读(201)  评论(0编辑  收藏  举报