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 }