題意:
思路:
首先,我們要開兩顆線段樹,一顆表示,當前節點爲白時,和子樹所組成的最大聯通塊大小是多少,另一顆表示,當前節點爲黑時,和子樹所組成的最大聯通塊大小是多少。
那麼我們查詢點u的答案的時候,就向上找到最遠的相同顏色的點v,點v所保存的答案就是u的答案(我們v爲最遠同色祖先)。
更新某個點u的顏色的時候,就是把u的父親和最遠同色祖先的父親,這一條路徑上的都更新(注意,黑白各更新一次,且將對應不同路徑),爲什麼是把u的父親和最遠同色祖先的父親更新一次,這個根據我們之前對他們的定義就能理解了,這裏用樹剖+線段樹維護即可。
那麼還有一個問題,怎麼快速找到最遠公共祖先,就是樹剖爬,然後二分某個鏈即可(注意你二分的時候左右值分別表示的是什麼)
最後,注意根,以及你在爬的時候,每個點表示的顏色
錯誤及反思:
卡了兩天,真的毒啊,各種邊界,各種細節,一個人慢慢摸索了好久才AC
這個代碼在spoj過了,在bzojT了,把線段樹改成樹狀數組應該就能AC了,可是我實在不想改了(不過代碼寫的很醜,主要是確實改煩了)
代碼:
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N =100010;
int tot=0,tid=1,n,q;
int top[N],si[N],fa[N],first[N],son[N],depth[N],id[N],rnk[N];
int cnt[N*4],segtree[2][N*4],lazy[2][N*4];//0 for white 1 for black
// cnt calculate for white so 0 for black 1 for white
struct E{
int to,next;
}e[N*2];
void build(int l,int r,int rt){
if(l==r){
segtree[1][rt]=si[rnk[l]];
segtree[0][rt]=1;
return ;
}
int m=(l+r)/2;
build(lson); build(rson);
}
void addedge(int x,int y){
e[tot].to=y;
e[tot].next=first[x];
first[x]=tot++;
}
void dfs1(int now,int bef,int dep){
fa[now]=bef;
depth[now]=dep;
si[now]=1;
for(int i=first[now];i!=-1;i=e[i].next)
if(e[i].to!=bef){
dfs1(e[i].to,now,dep+1);
si[now]+=si[e[i].to];
if(son[now]==-1) son[now]=e[i].to;
else son[now]=si[e[i].to]>si[son[now]]?e[i].to:son[now];
}
}
void dfs2(int now,int tp){
top[now]=tp;
id[now]=tid++;
if(son[now]!=-1) dfs2(son[now],tp);
for(int i=first[now];i!=-1;i=e[i].next)
if(e[i].to!=fa[now]&&e[i].to!=son[now])
dfs2(e[i].to,e[i].to);
}
void init(){
memset(first,-1,sizeof(first));
memset(son,-1,sizeof(son));
}
void pushdown(int x,int l,int r,int rt){
if(lazy[x][rt]){
lazy[x][rt<<1]+=lazy[x][rt];
lazy[x][rt<<1|1]+=lazy[x][rt];
segtree[x][rt<<1]+=lazy[x][rt];
segtree[x][rt<<1|1]+=lazy[x][rt];
lazy[x][rt]=0;
}
}
void changecnt(int p,int l,int r,int rt){
if(l==r){
cnt[rt]=!cnt[rt];
return ;
}
int m=(l+r)/2;
if(m>=p) changecnt(p,lson);
else changecnt(p,rson);
cnt[rt]=cnt[rt<<1]+cnt[rt<<1|1];
}
void changeseg(int L,int R,int v,int l,int r,int rt,int x){
if(L<=l&&R>=r){
lazy[x][rt]+=v;
segtree[x][rt]+=v;
return ;
}
pushdown(x,l,r,rt);
int m=(l+r)/2;
if(L<=m) changeseg(L,R,v,lson,x);
if(R>m) changeseg(L,R,v,rson,x);
}
int querycnt(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r) return cnt[rt];
int m=(l+r)/2,ans=0;
if(m>=L) ans+=querycnt(L,R,lson);
if(m<R) ans+=querycnt(L,R,rson);
return ans;
}
int queryseg(int p,int l,int r,int rt,int x){
if(l==r)return segtree[x][rt];
int m=(l+r)/2;
pushdown(x,l,r,rt);
if(m>=p) return queryseg(p,lson,x);
return queryseg(p,rson,x);
}
int getans(int u){
int f=top[u],col=querycnt(id[u],id[u],1,n,1);
while(f!=1){
int x=querycnt(id[f],id[u],1,n,1);
if(col&&x!=depth[u]-depth[f]+1) break;
if(!col&&x) break;
if(col!=querycnt(id[fa[f]],id[fa[f]],1,n,1)) break;
u=fa[f];
f=top[u];
}
while(id[u]>id[f]+1){
int m=(id[u]+id[f])/2;
int x=querycnt(m,id[u],1,n,1);
if(col){
if(x==depth[u]-depth[rnk[m]]+1) u=rnk[m];
else f=rnk[m];
}
else{
if(x==0) u=rnk[m];
else f=rnk[m];
}
}
if(querycnt(id[fa[u]],id[fa[u]],1,n,1)==col) u=fa[u];
return queryseg(id[u],1,n,1,!col);
}
void modify(int u){
int v=u;
int col=querycnt(id[u],id[u],1,n,1),num=queryseg(id[u],1,n,1,!col);
changecnt(id[u],1,n,1);
if(u==1) return ;
u=fa[u];
int f=top[u];
while(f!=1){
int x=querycnt(id[f],id[u],1,n,1);
if(col&&x!=depth[u]-depth[f]+1) break;
else if(col) changeseg(id[f],id[u],-num,1,n,1,!col);
if(!col&&x) break;
else if(!col) changeseg(id[f],id[u],-num,1,n,1,!col);
u=fa[f];
f=top[u];
}
while(id[u]>id[f]+1){
int m=(id[u]+id[f])/2;
int x=querycnt(m,id[u],1,n,1);
if(col){
if(x==depth[u]-depth[rnk[m]]+1){
changeseg(m+1,id[u],-num,1,n,1,!col);
u=rnk[m];
}
else f=rnk[m];
}
else{
if(x==0){
changeseg(m+1,id[u],-num,1,n,1,!col);
u=rnk[m];
}
else f=rnk[m];
}
}
if(u!=f&&col==querycnt(id[u],id[u],1,n,1)) changeseg(id[u],id[u],-num,1,n,1,!col);
if(col!=querycnt(id[u],id[u],1,n,1)) f=u;
changeseg(id[f],id[f],-num,1,n,1,!col);
u=v;
col=!col;
num=queryseg(id[u],1,n,1,!col);
u=fa[u];
f=top[u];
while(f!=1){
int x=querycnt(id[f],id[u],1,n,1);
if(col&&x!=depth[u]-depth[f]+1) break;
else if(col) changeseg(id[f],id[u],num,1,n,1,!col);
if(!col&&x) break;
else if(!col) changeseg(id[f],id[u],num,1,n,1,!col);
u=fa[f];
f=top[u];
}
while(id[u]>id[f]+1){
int m=(id[u]+id[f])/2;
int x=querycnt(m,id[u],1,n,1);
if(col){
if(x==depth[u]-depth[rnk[m]]+1){
changeseg(m+1,id[u],num,1,n,1,!col);
u=rnk[m];
}
else f=rnk[m];
}
else{
if(x==0){
changeseg(m+1,id[u],num,1,n,1,!col);
u=rnk[m];
}
else f=rnk[m];
}
}
if(u!=f&&col==querycnt(id[u],id[u],1,n,1)) changeseg(id[u],id[u],num,1,n,1,!col);
if(col!=querycnt(id[u],id[u],1,n,1)) f=u;
changeseg(id[f],id[f],num,1,n,1,!col);
return ;
}
int main(){
init();
scanf("%d",&n);
for(int i=0,u,v;i<n-1;i++){
scanf("%d%d",&u,&v);
addedge(u,v); addedge(v,u);
}
dfs1(1,1,1); dfs2(1,1);
for(int i=1;i<=n;i++) rnk[id[i]]=i;
build(1,n,1);
scanf("%d",&q);
while(q--){
int k,u;
scanf("%d%d",&k,&u);
if(k) modify(u);
else printf("%d\n",getans(u));
}
}