T1 words
题目大意: bzoj 4567
考试代码:
(如果不重建树的话会出锅 例子:
其中加粗的边为有$end$标记的节点,若不重建树,则左边$a$的$sz$为4,右边为3会先走右边
实际上应该先走左边(man太惨了。
T2 tree
题目大意:bzoj 4817
一棵树 支持三种操作:
1 x:把点x到根节点的路径上所有的点染上一种没有用过的新颜色
2 x y:求x到y的路径的权值
3 x:在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值
思路:
(之前看wls做过这道题,对大致思路有一个了解,当时感觉好神啊
维护每个点到根的路径的权值
这样两个询问的答案分别为$val_a+val_b-2*val_{lca}+1$与子树中的最大值,用线段树可以很方便的维护
对于修改,发现这个过程与$LCT$的$access$很像
使用$LCT$来维护修改,即对于修改,$access$该点,并在过程中修改
找到两个部分内最浅的点,然后用线段树一个$+1$一个$-1$修改即可非常完美的解决
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 #include<map> 11 #define ll long long 12 #define rep(i,s,t) for(int i=(s),i##end=(t);i<=i##end;++i) 13 #define dwn(i,s,t) for(int i=(s),i##end=(t);i>=i##end;--i) 14 #define ren for(int i=fst[x];i;i=nxt[i]) 15 #define MAXN 100100 16 using namespace std; 17 inline int read() 18 { 19 int x=0,f=1;char ch=getchar(); 20 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 21 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 22 return x*f; 23 } 24 int n,m,fst[MAXN],nxt[MAXN<<1],to[MAXN<<1],cnt,dep[MAXN]; 25 int fa[MAXN],sz[MAXN],hvs[MAXN],tot,bl[MAXN],in[MAXN]; 26 int mx[MAXN<<2],tag[MAXN<<2]; 27 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;} 28 void dfs(int x,int pa) 29 { 30 fa[x]=pa,sz[x]=1; 31 ren if(to[i]^pa) dep[to[i]]=dep[x]+1,dfs(to[i],x), 32 sz[x]+=sz[to[i]],hvs[x]=sz[to[i]]>sz[hvs[x]]?to[i]:hvs[x]; 33 } 34 void Dfs(int x,int anc) 35 { 36 bl[x]=anc,in[x]=++tot;if(!hvs[x]) return ; 37 Dfs(hvs[x],anc);ren if(to[i]^fa[x]&&to[i]^hvs[x]) Dfs(to[i],to[i]); 38 } 39 int lca(int a,int b) 40 { 41 for(;bl[a]!=bl[b];a=fa[bl[a]]) 42 if(dep[bl[a]]<dep[bl[b]]) swap(a,b); 43 return in[a]<in[b]?a:b; 44 } 45 void pshd(int k) 46 { 47 mx[k<<1]+=tag[k],mx[k<<1|1]+=tag[k]; 48 tag[k<<1]+=tag[k],tag[k<<1|1]+=tag[k],tag[k]=0; 49 } 50 void mdf(int k,int l,int r,int a,int b,int x) 51 { 52 if(l==a&&r==b) {tag[k]+=x,mx[k]+=x;return ;}int mid=l+r>>1; 53 if(tag[k]) pshd(k); 54 if(b<=mid) mdf(k<<1,l,mid,a,b,x); 55 else if(a>mid) mdf(k<<1|1,mid+1,r,a,b,x); 56 else {mdf(k<<1,l,mid,a,mid,x);mdf(k<<1|1,mid+1,r,mid+1,b,x);} 57 mx[k]=max(mx[k<<1],mx[k<<1|1]); 58 } 59 int query(int k,int l,int r,int a,int b) 60 { 61 if(l==a&&r==b) return mx[k];int mid=l+r>>1; 62 if(tag[k]) pshd(k); 63 if(b<=mid) return query(k<<1,l,mid,a,b); 64 else if(a>mid) return query(k<<1|1,mid+1,r,a,b); 65 else return max(query(k<<1,l,mid,a,mid),query(k<<1|1,mid+1,r,mid+1,b)); 66 } 67 namespace lct 68 { 69 int ch[MAXN][2],tag[MAXN],fa[MAXN]; 70 int which(int x) {return ch[fa[x]][1]==x;} 71 int isroot(int x) {return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x;} 72 void rotate(int x) 73 { 74 int f=fa[x],ff=fa[f],k=which(x); 75 if(!isroot(f)) ch[ff][ch[ff][1]==f]=x;fa[x]=ff; 76 ch[f][k]=ch[x][k^1],fa[ch[x][k^1]]=f,ch[x][k^1]=f,fa[f]=x; 77 } 78 void splay(int x) 79 { 80 for(int f;!isroot(x);rotate(x)) 81 if(!isroot(f=fa[x])) rotate(which(x)==which(f)?f:x); 82 } 83 int find(int x) {while(ch[x][0]) x=ch[x][0];return x;} 84 void access(int x) 85 { 86 for(int t=0,tmp;x;t=x,x=fa[x]) 87 { 88 splay(x); 89 if(ch[x][1]){tmp=find(ch[x][1]);mdf(1,1,n,in[tmp],in[tmp]+sz[tmp]-1,1);} 90 ch[x][1]=t;if(t){tmp=find(t);mdf(1,1,n,in[tmp],in[tmp]+sz[tmp]-1,-1);} 91 } 92 } 93 }; 94 int main() 95 { 96 n=read(),m=read();int a,b,c;rep(i,2,n) a=read(),b=read(),add(a,b),add(b,a); 97 dep[1]=1;dfs(1,0);Dfs(1,1);rep(i,1,n) mdf(1,1,n,in[i],in[i],dep[i]),lct::fa[i]=fa[i]; 98 while(m--) 99 { 100 c=read(),a=read(); 101 if(c==1) lct::access(a); 102 else if(c==2) 103 { 104 b=read(),c=lca(a,b); 105 printf("%d\n",query(1,1,n,in[a],in[a])+query(1,1,n,in[b],in[b])-2*query(1,1,n,in[c],in[c])+1); 106 } 107 else printf("%d\n",query(1,1,n,in[a],in[a]+sz[a]-1)); 108 } 109 }