[BZOJ3306]树
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3306]树相关的知识,希望对你有一定的参考价值。
为什么这道题会被打上‘LCT‘的tag呢?
不管怎么说先膜LCT
如果没有过于鬼畜的艹作,查询子树有一个方法就是用数据结构维护dfs序
此题仅有单点修改,于是我们考虑用线段树维护dfs序
先以1为根dfs一次
修改->线段树单点修改
子树最小值->线段树区间查询
还有一个艹作:换根
先约定记号:[lpos[x],rpos[x]]为x的子树在dfs序中所代表的区间
假如当前查询的点为x
①若lca(x,root)!=x,这种情况下的答案与根为1是相同的,即min{lpos[x]...rpos[x]}
②若lca(x,root)==x),说明x是root的祖先,需要去掉以y为根的子树,答案为min{min{1...lpos[y]-1},min{rpos[y]+1..n}},其中y为x向root方向的儿子
图画得好丑w
找y的话,找lca的时候顺便记录就好了
1 #include<stdio.h> 2 #define inf 2147483647 3 int v[100010],h[100010],nex[200010],to[200010],lpos[100010],rpos[100010],ev[100010],dep[100010],fa[100010][18],Tmin[300010],tot,n,M,root; 4 void add(int a,int b){ 5 tot++; 6 to[tot]=b; 7 nex[tot]=h[a]; 8 h[a]=tot; 9 } 10 void dfs(int x){ 11 tot++; 12 ev[tot]=v[x]; 13 lpos[x]=tot; 14 for(int i=h[x];i;i=nex[i]){ 15 if(to[i]!=fa[x][0]){ 16 fa[to[i]][0]=x; 17 dep[to[i]]=dep[x]+1; 18 dfs(to[i]); 19 } 20 } 21 rpos[x]=tot; 22 } 23 int min(int a,int b){return a<b?a:b;} 24 void swap(int&a,int&b){a^=b^=a^=b;} 25 int lca(int x,int y){ 26 if(dep[x]<dep[y])swap(x,y); 27 int i; 28 for(i=17;i>=0;i--){ 29 if(dep[fa[x][i]]>dep[y])x=fa[x][i]; 30 } 31 if(fa[x][0]==y) 32 return x; 33 else 34 x=fa[x][0]; 35 for(i=17;i>=0;i--){ 36 if(fa[x][i]!=fa[y][i]){ 37 x=fa[x][i]; 38 y=fa[y][i]; 39 } 40 } 41 return x; 42 } 43 int query(int s,int t){ 44 int ans=inf; 45 if(s>t)return ans; 46 for(s+=M-1,t+=M+1;s^t^1;s>>=1,t>>=1){ 47 if(~s&1)ans=min(ans,Tmin[s^1]); 48 if(t&1)ans=min(ans,Tmin[t^1]); 49 } 50 return ans; 51 } 52 int main(){ 53 int q,i,j,x,y; 54 char s[5]; 55 scanf("%d%d",&n,&q); 56 root=1; 57 for(i=1;i<=n;i++){ 58 scanf("%d%d",&x,v+i); 59 if(x)add(x,i); 60 } 61 tot=0; 62 dfs(1); 63 for(j=1;j<18;j++){ 64 for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1]; 65 } 66 for(M=1;M<n+2;M<<=1); 67 for(i=0;i<M;i++)Tmin[i+M]=inf; 68 for(i=1;i<=n;i++)Tmin[i+M]=ev[i]; 69 for(i=M-1;i>0;i--)Tmin[i]=min(Tmin[i<<1],Tmin[i<<1|1]); 70 while(q--){ 71 scanf("%s",s); 72 if(s[0]==‘V‘){ 73 scanf("%d%d",&x,&y); 74 i=lpos[x]+M; 75 Tmin[i]=y; 76 for(i>>=1;i;i>>=1)Tmin[i]=min(Tmin[i<<1],Tmin[i<<1|1]); 77 } 78 if(s[0]==‘E‘)scanf("%d",&root); 79 if(s[0]==‘Q‘){ 80 scanf("%d",&x); 81 if(x==root){ 82 printf("%d\\n",Tmin[1]); 83 continue; 84 } 85 y=lca(x,root); 86 if(fa[y][0]!=x) 87 printf("%d\\n",query(lpos[x],rpos[x])); 88 else 89 printf("%d\\n",min(query(1,lpos[y]-1),query(rpos[y]+1,n))); 90 } 91 } 92 }
以上是关于[BZOJ3306]树的主要内容,如果未能解决你的问题,请参考以下文章