點分樹借鑑了點分治的思想,將分治過程當中具備父子關係的重心連邊ios
造成了一顆高度爲 \(logn\) 的樹數組
這樣每一次分治時,咱們就不用從新去找重心,直接沿着點分樹向上跳便可數據結構
和點分治相比,點分樹能夠支持多組詢問spa
並且還可以進行修改操做,能夠解決一些強制在線的題目rest
點分樹有兩個性質:code
\(1\)、原樹上任意兩點 \(p,q\) 在點分樹上的 \(lca\) 必定在 \(p\) 到 \(q\) 的路徑上排序
\(2\)、點分樹的樹高是 \(logn\) 級別的遊戲
第一個性質決定了咱們能夠經過向上跳父親來處理與路徑有關的信息get
第二個性質則決定了咱們這麼作不會 \(T\)string
通常來講,點分樹的題都須要咱們在節點上維護兩個數據結構
一個存儲全部子樹對本身的貢獻,另外一個存儲全部子樹對父親的貢獻,計算答案時要容斥計算
由於樹高是 \(logn\) 的,因此這麼作的空間複雜度爲 \(nlogn\)
二維數組確定開不下,因此常常用 \(vector\) 來實現
查詢到點 \(x\) 距離小於等於 \(k\) 的全部點的權值之和,強制在線,支持修改
根據點分樹的第一個性質,咱們能夠枚舉其它點與點 \(x\) 的 \(lca\) 是哪個點,這個 \(lca\) 必定是點 \(x\) 在點分樹上的祖先節點
假設當前枚舉到的點是 \(y\)
若 \(y\) 知足條件,則有 \(dis(x,lca)+dis(y,lca) \leq k\)
因此只須要查詢到 \(lca\) 的距離小於等於 \(k-dis(x,lca)\) 的點便可
還要支持修改操做,能夠用數狀數組維護
可是這樣會有重複的狀況
由於咱們只是簡單地知足了距離關係,因此 \(x\) 和 \(y\) 在原樹上的 \(lca\) 不必定是當前的節點,還有多是當前點在點分樹上的子節點
所以要把子節點中距離 \(lca\) 的距離小於等於 \(k-dis(c,lca)\) 的貢獻刪除,這和點分治中的容斥是同樣的
可是要注意的是,點分樹中的父子節點在原樹上基本沒有什麼關係,因此不能直接在兒子節點的數狀數組中把這個貢獻減去
而要另開一個數狀數組記錄兒子節點在點分樹中的子樹對其父親的貢獻
查詢時,咱們從當前點開始一直跳點分樹的父親,容斥計算貢獻
修改時,也是暴力跳父親,在數狀數組上加入當前貢獻與以前貢獻的差
對於一開始就有的價值,咱們直接做爲修改操做處理
時間複雜度 \(mlog^2n\)
#include<cstdio> #include<cstring> #include<iostream> #include<vector> #include<algorithm> #define rg register inline int read(){ rg int x=0,fh=1; rg char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') fh=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*fh; } const int maxn=1e5+5; int h[maxn],tot=1,n,m,latans; struct asd{ int to,nxt; }b[maxn<<1]; void ad(rg int aa,rg int bb){ b[tot].to=bb; b[tot].nxt=h[aa]; h[aa]=tot++; } int siz[maxn],dep[maxn],fa[maxn],son[maxn]; void dfs1(rg int now,rg int lat){ siz[now]=1; dep[now]=dep[lat]+1; fa[now]=lat; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat) continue; dfs1(u,now); siz[now]+=siz[u]; if(son[now]==0 || siz[u]>siz[son[now]]) son[now]=u; } } int tp[maxn],val[maxn]; void dfs2(rg int now,rg int top){ tp[now]=top; if(son[now]) dfs2(son[now],top); for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==son[now] || u==fa[now]) continue; dfs2(u,u); } } int getlca(rg int xx,rg int yy){ while(tp[xx]!=tp[yy]){ if(dep[tp[xx]]<dep[tp[yy]]) std::swap(xx,yy); xx=fa[tp[xx]]; } return dep[xx]<dep[yy]?xx:yy; } int getdis(rg int xx,rg int yy){ return dep[xx]+dep[yy]-2*dep[getlca(xx,yy)]; } int rt,totsiz,maxsiz[maxn]; bool vis[maxn]; void getroot(rg int now,rg int lat){ siz[now]=1,maxsiz[now]=0; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getroot(u,now); siz[now]+=siz[u]; maxsiz[now]=std::max(maxsiz[now],siz[u]); } maxsiz[now]=std::max(maxsiz[now],totsiz-siz[now]); if(maxsiz[now]<maxsiz[rt]) rt=now; } int lb(rg int xx){ return xx&-xx; } struct BIT{ std::vector<int> tr; int trsiz; void init(rg int now){ for(rg int i=0;i<=now;i++) tr.push_back(0); trsiz=now; } void ad(rg int wz,rg int val){ wz=std::min(wz+1,trsiz); for(rg int i=wz;i<=trsiz;i+=lb(i)){ tr[i]+=val; } } int cx(rg int wz){ wz=std::min(wz+1,trsiz); rg int nans=0; for(rg int i=wz;i>0;i-=lb(i)){ nans+=tr[i]; } return nans; } }tr1[maxn],tr2[maxn]; int newfa[maxn]; void getsiz(rg int now,rg int lat){ siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getsiz(u,now); siz[now]+=siz[u]; } } void predfs(rg int now){ vis[now]=1; getsiz(now,0); rg int tmp=siz[now]+3; tr1[now].init(tmp); tr2[now].init(tmp); for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(vis[u]) continue; totsiz=siz[u],rt=0; getroot(u,now); newfa[rt]=now; predfs(rt); } }//構建點分樹 void updat(rg int now,rg int nval){ for(rg int i=now;i;i=newfa[i]){ tr1[i].ad(getdis(now,i),nval); } for(rg int i=now;newfa[i];i=newfa[i]){ tr2[i].ad(getdis(newfa[i],now),nval); } }//更新答案 int solve(rg int now,rg int k){ rg int nans=tr1[now].cx(k); for(rg int i=now;newfa[i];i=newfa[i]){ rg int tmp=getdis(newfa[i],now); if(k>=tmp) nans+=tr1[newfa[i]].cx(k-tmp)-tr2[i].cx(k-tmp); } return nans; }//查詢答案 int main(){ memset(h,-1,sizeof(h)); n=read(),m=read(); for(rg int i=1;i<=n;i++) val[i]=read(); rg int aa,bb,cc; for(rg int i=1;i<n;i++){ aa=read(),bb=read(); ad(aa,bb),ad(bb,aa); } dfs1(1,0); dfs2(1,1); maxsiz[0]=0x3f3f3f3f,rt=0,totsiz=n; getroot(1,0); predfs(rt); for(rg int i=1;i<=n;i++) updat(i,val[i]); for(rg int i=1;i<=m;i++){ aa=read(),bb=read(),cc=read(); bb^=latans,cc^=latans; if(aa==0) printf("%d\n",latans=solve(bb,cc)); else { updat(bb,cc-val[bb]); val[bb]=cc; } } return 0; }
查詢點 \(u\) 到全部年齡在區間 \([l,r]\) 中妖怪的距離,強制在線
一樣能夠在點分樹上套數據結構解決
設當前的點爲 \(x\),當前點的兒子節點爲 \(u\)
那麼該點對答案的貢獻就是\(x\)子樹中年齡在 \([l,r]\) 之間的妖怪到 \(x\) 的距離之和 - \(u\) 子樹中年齡在 \([l,r]\) 之間的妖怪到 \(x\) 的距離之和+(\(x\)子樹中年齡在 \([l,r]\) 之間的妖怪個數- \(u\) 子樹中年齡在 \([l,r]\) 之間的妖怪個數) \(\times\) 查詢點到節點 \(x\) 的距離
由於沒有修改操做,因此直接用 \(vector\) ,\(vector\) 中存儲妖怪的年齡以及妖怪到當前點的距離
\(vector\) 要開兩個,一個記錄對當前點的貢獻,一個記錄對父親節點的貢獻
對於年齡的限制,咱們在建好點分樹後直接把 \(vector\) 中的元素按照年齡從小到大排序
而後記錄一個前綴和,查詢時二分便可
而妖怪的個數就是二分時下標之差
距離之和直接暴力跳父親算一下就好了
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<iostream> #define rg register inline int read(){ rg int x=0,fh=1; rg char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') fh=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*fh; } const int maxn=1e6+5; int h[maxn],tot=1; struct asd{ int to,nxt,val; }b[maxn]; void ad(rg int aa,rg int bb,rg int cc){ b[tot].to=bb; b[tot].nxt=h[aa]; b[tot].val=cc; h[aa]=tot++; } int n,q,maxage,x[maxn],siz[maxn],fa[maxn],dep[maxn],son[maxn]; long long dis[maxn]; void dfs1(rg int now,rg int lat){ fa[now]=lat; dep[now]=dep[lat]+1; siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat) continue; dis[u]=dis[now]+b[i].val; dfs1(u,now); siz[now]+=siz[u]; if(siz[son[now]]<siz[u]) son[now]=u; } } int tp[maxn]; void dfs2(rg int now,rg int top){ tp[now]=top; if(son[now]) dfs2(son[now],top); for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==son[now] || u==fa[now]) continue; dfs2(u,u); } } int getlca(rg int xx,rg int yy){ while(tp[xx]!=tp[yy]){ if(dep[tp[xx]]<dep[tp[yy]]) std::swap(xx,yy); xx=fa[tp[xx]]; } return dep[xx]<dep[yy]?xx:yy; } long long getdis(rg int xx,rg int yy){ return dis[xx]+dis[yy]-2LL*dis[getlca(xx,yy)]; } int maxsiz[maxn],totsiz,rt; bool vis[maxn]; void getroot(rg int now,rg int lat){ maxsiz[now]=0,siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getroot(u,now); siz[now]+=siz[u]; maxsiz[now]=std::max(maxsiz[now],siz[u]); } maxsiz[now]=std::max(maxsiz[now],totsiz-siz[now]); if(maxsiz[rt]>maxsiz[now]) rt=now; } struct Node{ int age; long long dis; Node(){} Node(rg int aa,rg long long bb){ age=aa,dis=bb; } friend bool operator <(const Node& A,const Node& B){ return A.age<B.age; } }; std::vector<Node> vec[2][maxn]; void getsiz(rg int now,rg int lat){ siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getsiz(u,now); siz[now]+=siz[u]; } } int newfa[maxn]; void predfs(rg int now){ vis[now]=1; getsiz(now,0); for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(!vis[u]){ rt=0,totsiz=siz[u]; getroot(u,now); newfa[rt]=now; predfs(rt); } } } void updat(rg int now){ for(rg int i=now;i;i=newfa[i]){ vec[0][i].push_back(Node(x[now],getdis(i,now))); } for(rg int i=now;newfa[i];i=newfa[i]){ vec[1][i].push_back(Node(x[now],getdis(newfa[i],now))); } } long long latans; int nowsiz; long long cx(rg int op,rg int now,rg int l,rg int r){ rg int nl=std::lower_bound(vec[op][now].begin(),vec[op][now].end(),Node(l,0))-vec[op][now].begin()-1; rg int nr=std::upper_bound(vec[op][now].begin(),vec[op][now].end(),Node(r,0))-vec[op][now].begin()-1; nowsiz=nr-nl; if(nr<0) return 0; if(nl<0) return vec[op][now][nr].dis; return vec[op][now][nr].dis-vec[op][now][nl].dis; } long long solve(rg int now,rg int l,rg int r){ rg long long nans=cx(0,now,l,r); rg int sizfa,siznow; for(rg int i=now;newfa[i];i=newfa[i]){ nans+=cx(0,newfa[i],l,r); sizfa=nowsiz; nans-=cx(1,i,l,r); siznow=nowsiz; nans+=1LL*(sizfa-siznow)*getdis(newfa[i],now); } return nans; } int main(){ memset(h,-1,sizeof(h)); n=read(),q=read(),maxage=read(); for(rg int i=1;i<=n;i++) x[i]=read(); rg int aa,bb,cc,l,r; for(rg int i=1;i<n;i++){ aa=read(),bb=read(),cc=read(); ad(aa,bb,cc); ad(bb,aa,cc); } dfs1(1,0); dfs2(1,1); maxsiz[0]=0x3f3f3f3f,rt=0,totsiz=n; getroot(1,0); predfs(rt); for(rg int i=1;i<=n;i++) updat(i); for(rg int i=1;i<=n;i++){ std::sort(vec[0][i].begin(),vec[0][i].end()); std::sort(vec[1][i].begin(),vec[1][i].end()); for(rg int j=1;j<vec[0][i].size();j++) vec[0][i][j].dis+=vec[0][i][j-1].dis; for(rg int j=1;j<vec[1][i].size();j++) vec[1][i][j].dis+=vec[1][i][j-1].dis; } for(rg int i=1;i<=q;i++){ aa=read(),bb=read(),cc=read(); l=std::min((bb+latans)%maxage,(cc+latans)%maxage); r=std::max((bb+latans)%maxage,(cc+latans)%maxage); latans=solve(aa,l,r); printf("%lld\n",latans); } return 0; }
這道題實際上就是讓咱們尋找帶權重心
假設當前的點爲 \(x\),\(x\) 的子節點爲 \(u\),\(u\) 和 \(x\) 之間的邊權爲 \(len\)
若是 \(x\) 子樹內一點 \(u\) 更優,那麼必定有 \((totsiz-siz[u]) \times len - siz[u] \times len <0\)
由於邊權是正的,因此就有 \(2siz[u]>totsiz\)
顯然知足這個條件的兒子只有一個
由於每個點的度數不會超過 \(20\)
所以能夠在點分樹上暴力地尋找
注意必定要在點分樹上找,不要跑到原樹上去找,不然複雜度就假了
若是用 \(st\) 表 \(O(1)\) 求 \(lca\),那麼複雜度就是 \(20qlog^2n\)
但實際上跑得尚未樹剖快
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> #include<iostream> #define rg register inline int read(){ rg int x=0,fh=1; rg char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') fh=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*fh; } const int maxn=2e5+5; int h[maxn],tot=1; struct asd{ int to,nxt,val; }b[maxn<<1]; void ad(rg int aa,rg int bb,rg int cc){ b[tot].to=bb; b[tot].nxt=h[aa]; b[tot].val=cc; h[aa]=tot++; } int n,q,x[maxn],siz[maxn],eul[maxn],dfnc,dep[maxn],lg[maxn<<1],st[maxn<<1][22],rk[maxn<<1]; long long dis[maxn]; void dfs(rg int now,rg int lat){ dep[now]=dep[lat]+1; eul[now]=++dfnc; rk[dfnc]=now; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat) continue; dis[u]=dis[now]+b[i].val; dfs(u,now); rk[++dfnc]=now; } } void prest(){ for(rg int i=2;i<=dfnc;i++) lg[i]=lg[i>>1]+1; for(rg int i=1;i<=dfnc;i++) st[i][0]=rk[i]; for(rg int j=1;j<=20;j++){ for(rg int i=1;i+(1<<j)-1<=dfnc;i++){ if(dep[st[i][j-1]]<dep[st[i+(1<<(j-1))][j-1]]) st[i][j]=st[i][j-1]; else st[i][j]=st[i+(1<<(j-1))][j-1]; } } } int getlca(rg int xx,rg int yy){ xx=eul[xx],yy=eul[yy]; if(xx>yy) std::swap(xx,yy); rg int nk=lg[yy-xx+1]; return dep[st[xx][nk]]<dep[st[yy-(1<<nk)+1][nk]]?st[xx][nk]:st[yy-(1<<nk)+1][nk]; } long long getdis(rg int xx,rg int yy){ return dis[xx]+dis[yy]-2LL*dis[getlca(xx,yy)]; } int maxsiz[maxn],totsiz,rt; bool vis[maxn]; void getroot(rg int now,rg int lat){ maxsiz[now]=0,siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getroot(u,now); siz[now]+=siz[u]; maxsiz[now]=std::max(maxsiz[now],siz[u]); } maxsiz[now]=std::max(maxsiz[now],totsiz-siz[now]); if(maxsiz[rt]>maxsiz[now]) rt=now; } void getsiz(rg int now,rg int lat){ siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getsiz(u,now); siz[now]+=siz[u]; } } int newfa[maxn]; std::vector<std::pair<int,int> > g[maxn]; void predfs(rg int now){ vis[now]=1; getsiz(now,0); for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(!vis[u]){ rt=0,totsiz=siz[u]; getroot(u,now); newfa[rt]=now; g[now].push_back(std::make_pair(u,rt)); predfs(rt); } } } long long sum1[maxn],sum2[maxn]; int siz1[maxn],siz2[maxn]; void updat(rg int now,rg int val){ for(rg int i=now;i;i=newfa[i]){ sum1[i]+=1LL*getdis(now,i)*val; siz1[i]+=val; } for(rg int i=now;newfa[i];i=newfa[i]){ sum2[i]+=1LL*getdis(now,newfa[i])*val; siz2[i]+=val; } } long long cx(rg int now){ rg long long nans=sum1[now]; for(rg int i=now;newfa[i];i=newfa[i]){ nans+=sum1[newfa[i]]; nans-=sum2[i]; nans+=1LL*getdis(newfa[i],now)*(siz1[newfa[i]]-siz2[i]); } return nans; } long long solve(rg int now){ rg long long tmp=cx(now); for(rg int i=0;i<g[now].size();i++){ if(cx(g[now][i].first)<tmp) return solve(g[now][i].second); } return tmp; } int main(){ memset(h,-1,sizeof(h)); n=read(),q=read(); rg int aa,bb,cc; for(rg int i=1;i<n;i++){ aa=read(),bb=read(),cc=read(); ad(aa,bb,cc); ad(bb,aa,cc); } dfs(1,0); prest(); maxsiz[0]=0x3f3f3f3f,rt=0,totsiz=n; getroot(1,0); predfs(rt); memset(vis,0,sizeof(vis)); rt=0,totsiz=n; getroot(1,0); for(rg int i=1;i<=q;i++){ aa=read(),bb=read(); updat(aa,bb); printf("%lld\n",solve(rt)); } return 0; }
和其它點分樹的題目同樣,對於每個節點咱們開兩個堆,防止同一個子樹內的節點對父親節點作屢次貢獻
一個堆裏存點分樹中 \(u\) 的子樹全部點到點分樹中 \(u\) 的父親的距離
另外一個堆裏存點分樹中 \(u\) 的全部兒子對 \(u\) 貢獻的最大值
那麼答案就是第二個堆中最大值與次大值之和
加入貢獻時,咱們直接扔到大根堆裏就能夠了
刪除貢獻時,咱們再開一個堆,堆裏面存儲全部已經刪除過的元素
查詢時只要不斷彈兩個堆的堆頂,直到一個堆爲空或者兩個堆堆頂的元素不相同爲止
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<queue> #include<iostream> #define rg register inline int read(){ rg int x=0,fh=1; rg char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') fh=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*fh; } const int maxn=1e5+5; int h[maxn],tot=1; struct asd{ int to,nxt; }b[maxn<<1]; void ad(rg int aa,rg int bb){ b[tot].to=bb; b[tot].nxt=h[aa]; h[aa]=tot++; } int n,q,siz[maxn],fa[maxn],dep[maxn],son[maxn]; void dfs1(rg int now,rg int lat){ fa[now]=lat; dep[now]=dep[lat]+1; siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat) continue; dfs1(u,now); siz[now]+=siz[u]; if(siz[son[now]]<siz[u]) son[now]=u; } } int tp[maxn]; void dfs2(rg int now,rg int top){ tp[now]=top; if(son[now]) dfs2(son[now],top); for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==son[now] || u==fa[now]) continue; dfs2(u,u); } } int getlca(rg int xx,rg int yy){ while(tp[xx]!=tp[yy]){ if(dep[tp[xx]]<dep[tp[yy]]) std::swap(xx,yy); xx=fa[tp[xx]]; } return dep[xx]<dep[yy]?xx:yy; } int getdis(rg int xx,rg int yy){ return dep[xx]+dep[yy]-2*dep[getlca(xx,yy)]; } int maxsiz[maxn],totsiz,rt; bool vis[maxn]; void getroot(rg int now,rg int lat){ maxsiz[now]=0,siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getroot(u,now); siz[now]+=siz[u]; maxsiz[now]=std::max(maxsiz[now],siz[u]); } maxsiz[now]=std::max(maxsiz[now],totsiz-siz[now]); if(maxsiz[rt]>maxsiz[now]) rt=now; } void getsiz(rg int now,rg int lat){ siz[now]=1; for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(u==lat || vis[u]) continue; getsiz(u,now); siz[now]+=siz[u]; } } int newfa[maxn]; void predfs(rg int now){ vis[now]=1; getsiz(now,0); for(rg int i=h[now];i!=-1;i=b[i].nxt){ rg int u=b[i].to; if(!vis[u]){ rt=0,totsiz=siz[u]; getroot(u,now); newfa[rt]=now; predfs(rt); } } } char s[maxn]; struct Splay{ std::priority_queue<int> q1; std::priority_queue<int> q2; void updat(){ for(;!q1.empty() && !q2.empty() && q1.top()==q2.top();){ q1.pop(); q2.pop(); } } void insert(rg int val){ q1.push(val); } void pop(rg int val){ q2.push(val); } int getmax(){ updat(); return q1.top(); } int getsec(){ updat(); rg int now1=q1.top();q1.pop(); updat(); rg int now2=q1.top();q1.pop(); q1.push(now1),q1.push(now2); return now2; } int size(){ return q1.size()-q2.size(); } }ansnow[maxn],ansfa[maxn],ans; void updat(rg int now){ vis[now]^=1; if(vis[now]==0){ if(ansnow[now].size()>=2) ans.pop(ansnow[now].getmax()+ansnow[now].getsec()); ansnow[now].insert(0); if(ansnow[now].size()>=2) ans.insert(ansnow[now].getmax()+ansnow[now].getsec()); for(rg int i=now;newfa[i];i=newfa[i]){ if(ansnow[newfa[i]].size()>=2) ans.pop(ansnow[newfa[i]].getmax()+ansnow[newfa[i]].getsec()); rg int ndis=getdis(now,newfa[i]); if(ansfa[i].size()) ansnow[newfa[i]].pop(ansfa[i].getmax()); ansfa[i].insert(ndis); if(ansfa[i].size()) ansnow[newfa[i]].insert(ansfa[i].getmax()); if(ansnow[newfa[i]].size()>=2) ans.insert(ansnow[newfa[i]].getmax()+ansnow[newfa[i]].getsec()); } } else { if(ansnow[now].size()>=2) ans.pop(ansnow[now].getmax()+ansnow[now].getsec()); ansnow[now].pop(0); if(ansnow[now].size()>=2) ans.insert(ansnow[now].getmax()+ansnow[now].getsec()); for(rg int i=now;newfa[i];i=newfa[i]){ if(ansnow[newfa[i]].size()>=2) ans.pop(ansnow[newfa[i]].getmax()+ansnow[newfa[i]].getsec()); rg int ndis=getdis(now,newfa[i]); if(ansfa[i].size()) ansnow[newfa[i]].pop(ansfa[i].getmax()); ansfa[i].pop(ndis); if(ansfa[i].size()) ansnow[newfa[i]].insert(ansfa[i].getmax()); if(ansnow[newfa[i]].size()>=2) ans.insert(ansnow[newfa[i]].getmax()+ansnow[newfa[i]].getsec()); } } } int cnt; int main(){ memset(h,-1,sizeof(h)); n=read(); rg int aa,bb; for(rg int i=1;i<n;i++){ aa=read(),bb=read(); ad(aa,bb); ad(bb,aa); } dfs1(1,0); dfs2(1,1); maxsiz[0]=0x3f3f3f3f,rt=0,totsiz=n; getroot(1,0); predfs(rt); q=read(); memset(vis,0,sizeof(vis)); for(rg int i=1;i<=n;i++){ for(rg int j=i;newfa[j];j=newfa[j]){ ansfa[j].insert(getdis(i,newfa[j])); } } for(rg int i=1;i<=n;i++){ ansnow[i].insert(0); if(newfa[i] && ansfa[i].size()) ansnow[newfa[i]].insert(ansfa[i].getmax()); } for(rg int i=1;i<=n;i++){ if(ansnow[i].size()>=2) ans.insert(ansnow[i].getmax()+ansnow[i].getsec()); } cnt=n; for(rg int i=1;i<=q;i++){ scanf("%s",s+1); if(s[1]=='G'){ if(cnt==0) printf("-1\n"); else if(cnt==1) printf("0\n"); else printf("%d\n",ans.getmax()); } else { aa=read(); if(vis[aa]) cnt++; else cnt--; updat(aa); } } return 0; }