bzoj4817/luogu3703 树点涂色 (LCT+dfs序+线段树)

我们发现,这个染色的操作他就很像LCT中access的操作(为什么??),然后就自然而然地想到,其实一个某条路径上的颜色数量,就是我们做一个只有access操作的LCT,这条路径经过的splay的数量

然后考虑怎么样来维护这个数量。access的过程中,有实边变虚边、虚边变实边的操作,对应过来,实边变虚边,就是以(断掉的那个子splay树中的在原树中最浅的点)为根的子树中 每个点到根的颜色数++(多拆出来了一个splay嘛),虚边变实边同理,不过是--

这样就可以再用一个线段树维护dfs序了,第三个询问就是线段树上的最大值

第二个询问,如果有x,y,lca,那x到y路径上的颜色数就是num[x]+num[y]-2*num[lca]+1,num[i]就是刚才线段树记的那个

  1 #include<bits/stdc++.h>
  2 #define pa pair<int,int>
  3 #define CLR(a,x) memset(a,x,sizeof(a))
  4 using namespace std;
  5 typedef long long ll;
  6 const int maxn=1e5+10;
  7 
  8 inline ll rd(){
  9     ll x=0;char c=getchar();int neg=1;
 10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
 11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
 12     return x*neg;
 13 }
 14 
 15 int N,M;
 16 int eg[maxn*2][2],egh[maxn],ect;
 17 int dep[maxn],dfn[maxn][2],fa[maxn],ch[maxn][2],tot;
 18 int bf[maxn][20],ma[maxn*4],laz[maxn*4],id[maxn];
 19 
 20 inline void adeg(int a,int b){
 21     eg[++ect][0]=b,eg[ect][1]=egh[a];egh[a]=ect;
 22 }
 23 
 24 void dfs(int x){
 25     dfn[x][0]=++tot;id[tot]=x;
 26     for(int i=0;bf[x][i]&&bf[bf[x][i]][i];i++)
 27         bf[x][i+1]=bf[bf[x][i]][i];
 28     for(int i=egh[x];i;i=eg[i][1]){
 29         int b=eg[i][0];
 30         if(b==fa[x]) continue;
 31         fa[b]=bf[b][0]=x;dep[b]=dep[x]+1;
 32         dfs(b);
 33     }
 34     dfn[x][1]=tot;
 35 }
 36 
 37 inline int getlca(int x,int y){
 38     if(dep[x]<dep[y]) swap(x,y);
 39     for(int i=log2(dep[x]-dep[y]);i>=0&&dep[x]!=dep[y];i--){
 40         if(dep[bf[x][i]]>=dep[y])
 41             x=bf[x][i];
 42     }
 43     if(x==y) return x;
 44     for(int i=log2(dep[x]);i>=0;i--){
 45         if(bf[x][i]!=bf[y][i])
 46             x=bf[x][i],y=bf[y][i];
 47     }
 48     return bf[x][0];
 49 }
 50 
 51 inline bool nroot(int x){return x==ch[fa[x]][0]||x==ch[fa[x]][1];}
 52 inline bool isrt(int x){return x==ch[fa[x]][1];}
 53 
 54 inline void rotate(int x){
 55     int f=fa[x],ff=fa[fa[x]];bool b=isrt(x);
 56     fa[x]=ff;if(nroot(f)) ch[ff][isrt(f)]=x;
 57     fa[ch[x][!b]]=f,ch[f][b]=ch[x][!b];
 58     fa[f]=x,ch[x][!b]=f;
 59 }
 60 
 61 inline void splay(int x){
 62     while(nroot(x)&&nroot(fa[x])){
 63         if(isrt(x)==isrt(fa[x])) rotate(fa[x]);
 64         else rotate(x);rotate(x);
 65     }if(nroot(x)) rotate(x);
 66 }
 67 
 68 inline int getl(int x){
 69     while(ch[x][0]) x=ch[x][0];
 70     return x;
 71 }
 72 
 73 inline void update(int p){ma[p]=max(ma[p<<1],ma[p<<1|1]);}
 74 inline void pushdown(int p){
 75     if(!laz[p]) return;
 76     int a=p<<1,b=p<<1|1;
 77     laz[a]+=laz[p],laz[b]+=laz[p];
 78     ma[a]+=laz[p],ma[b]+=laz[p];
 79     laz[p]=0;
 80 }
 81 
 82 inline void build(int p,int l,int r){
 83     if(l==r) ma[p]=dep[id[l]];
 84     else{
 85         int m=l+r>>1;
 86         build(p<<1,l,m);
 87         build(p<<1|1,m+1,r);
 88         update(p);
 89     }
 90 }
 91 inline void add(int p,int l,int r,int x,int y,int z){
 92     // printf("%d %d %d %d %d\n",p,l,r,x,y);
 93     if(x<=l&&r<=y){
 94         ma[p]+=z;laz[p]+=z;
 95     }else{
 96         pushdown(p);
 97         int m=l+r>>1;
 98         if(x<=m) add(p<<1,l,m,x,y,z);
 99         if(y>=m+1) add(p<<1|1,m+1,r,x,y,z);
100         update(p);
101     }
102 }
103 inline int query(int p,int l,int r,int x,int y){
104     if(!x||!y) return 0;
105     if(x<=l&&r<=y) return ma[p];
106     pushdown(p);
107     int m=l+r>>1,re=0;
108     if(x<=m) re=query(p<<1,l,m,x,y);
109     if(y>=m+1) re=max(re,query(p<<1|1,m+1,r,x,y));
110     return re;
111 }
112 
113 inline void access(int x){
114     for(int y=0;x;y=x,x=fa[x]){
115         splay(x);
116         int a=getl(ch[x][1]),b=getl(y);
117         // printf("!%d %d\n",a,b);
118         if(a) add(1,1,N,dfn[a][0],dfn[a][1],1);
119         if(b) add(1,1,N,dfn[b][0],dfn[b][1],-1);
120         ch[x][1]=y;
121     }
122 }
123 
124 inline int gettop(int x){
125     while(nroot(x)) x=fa[x];
126     return x;
127 }
128 
129 int main(){
130     //freopen("","r",stdin);
131     int i,j,k;
132     N=rd(),M=rd();
133     for(i=1;i<N;i++){
134         int a=rd(),b=rd();
135         adeg(a,b);adeg(b,a);
136     }
137     dep[1]=1;dfs(1);
138     build(1,1,N);
139     for(i=1;i<=M;i++){
140         int a=rd(),x=rd();
141         if(a==1)  access(x);
142         else if(a==2){
143             int y=rd();
144             int lca=getlca(x,y);
145             // printf("%d %d\n",x,y)
146             printf("%d\n",query(1,1,N,dfn[x][0],dfn[x][0])+
147                 query(1,1,N,dfn[y][0],dfn[y][0])-
148                 2*query(1,1,N,dfn[lca][0],dfn[lca][0])+1);
149         }else{
150             printf("%d\n",query(1,1,N,dfn[x][0],dfn[x][1]));
151         }
152     }
153     return 0;
154 }

 

posted @ 2018-10-19 14:56  Ressed  阅读(270)  评论(0编辑  收藏  举报