对于一个节点,用树剖、线段树维护它为黑/ 白色时它所在联通块大小(仅限于以它为根的子树)。
由于是单点修改,可能受影响的只有其父亲、父亲的父亲、父亲的父亲的父亲、、、
因此把log个区间全部改掉就好了。
但是细节奇多无比。
还有,图中每一种情况都可能碰到根,请自行特判。
对于询问,只需不停跳爸爸,找到联通块内离它最远的颜色相同的祖先,单点查询即可。
昨晚调了半天,上BZOJ一交,发现自己T了。
然后上Vjudge上一交,半天都跑不出来,估计也T了,然后只能去睡觉了QAQ。
然而今早起来一看突然发现A了,删掉O2重交一发,发现跑得更快了?!
反正最后用了210秒死。
蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤蛤
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define G getchar()
#define LL long long
#define pll pair<int,int>
#define mkp make_pair
#define X first
#define Y second
const int N=100005;
int n;bool col[N];
int he[N],ne[N<<1],to[N<<1],tot;
int sz[N],dad[N],son[N],dfn[N],nfd[N],cnt,pre[N];
LL sz0[N<<2],sz1[N<<2],lz0[N<<2],lz1[N<<2];int flg[N<<2];
void read(int &x){
char ch=getchar();
while(ch<48||ch>57)ch=G;
for(x=0;ch>=48&&ch<=57;ch=G)x=x*10+ch-48;
}
void add(int x,int y){
to[++tot]=y;ne[tot]=he[x];he[x]=tot;
}
void DFS1(int x,int e){
int y,i;sz[x]=1;
for(i=he[x];i;i=ne[i])if(i!=e){
pre[y=to[i]]=x;
DFS1(y,i^1);
if(sz[son[x]]<sz[y])son[x]=y;
sz[x]+=sz[y];
}
}
void DFS2(int x){
int i,y;nfd[dfn[x]=++cnt]=x;
dad[x]=son[pre[x]]==x?dad[pre[x]]:x;
if(son[x])DFS2(son[x]);
for(i=he[x];i;i=ne[i])if(!dfn[y=to[i]])
DFS2(y);
}
void up0(int num){
sz0[num]=sz0[num<<1]+sz0[num<<1|1];
}
void build0(int l,int r,int num){
if(l==r){
sz0[num]=sz[nfd[l]];return;
}
int mid=l+r>>1;
build0(l,mid,num<<1);build0(mid+1,r,num<<1|1);
up0(num);
}
void up1(int num){
sz1[num]=sz1[num<<1]+sz1[num<<1|1];
}
void build1(int l,int r,int num){
if(l==r){
sz1[num]=1;return;
}
int mid=l+r>>1;
build1(l,mid,num<<1);build1(mid+1,r,num<<1|1);
up1(num);
}
void pd0(int x,int num){
if(x>1){
lz0[num<<1]+=lz0[num];
lz0[num<<1|1]+=lz0[num];
sz0[num<<1]+=lz0[num]*(x+1>>1);
sz0[num<<1|1]+=lz0[num]*(x>>1);
}
lz0[num]=0;
}
LL query0(int x,int l,int r,int num){
if(l==r)return sz0[num];
int mid=l+r>>1;
pd0(r-l+1,num);
if(x<=mid)return query0(x,l,mid,num<<1);
return query0(x,mid+1,r,num<<1|1);
}
void pd1(int x,int num){
if(x>1){
lz1[num<<1]+=lz1[num];
lz1[num<<1|1]+=lz1[num];
sz1[num<<1]+=lz1[num]*(x+1>>1);
sz1[num<<1|1]+=lz1[num]*(x>>1);
}
lz1[num]=0;
}
LL query1(int x,int l,int r,int num){
if(l==r)return sz1[num];
int mid=l+r>>1;
pd1(r-l+1,num);
if(x<=mid)return query1(x,l,mid,num<<1);
return query1(x,mid+1,r,num<<1|1);
}
void up2(int num){
flg[num]=flg[num<<1]==flg[num<<1|1]?flg[num<<1]:2;
}
void modify2(int x,int l,int r,int num){
if(l==r){
flg[num]=col[nfd[l]];return;
}
int mid=l+r>>1;
if(x<=mid)modify2(x,l,mid,num<<1);
else modify2(x,mid+1,r,num<<1|1);
up2(num);
}
int query2(int L,int R,int l,int r,int num){
if(L<=l&&r<=R)return flg[num];
int mid=l+r>>1;
if(R<=mid)return query2(L,R,l,mid,num<<1);
if(L>mid)return query2(L,R,mid+1,r,num<<1|1);
int tmp=query2(L,R,l,mid,num<<1);
return tmp==2||query2(L,R,mid+1,r,num<<1|1)!=tmp?2:tmp;
}
void modify0(int L,int R,LL x,int l,int r,int num){
if(L<=l&&r<=R){
lz0[num]+=x;
sz0[num]+=(r-l+1)*x;
return;
}
pd0(r-l+1,num);
int mid=l+r>>1;
if(L<=mid)modify0(L,R,x,l,mid,num<<1);
if(R>mid)modify0(L,R,x,mid+1,r,num<<1|1);
up0(num);
}
void modify1(int L,int R,LL x,int l,int r,int num){
if(L<=l&&r<=R){
lz1[num]+=x;
sz1[num]+=(r-l+1)*x;
return;
}
pd1(r-l+1,num);
int mid=l+r>>1;
if(L<=mid)modify1(L,R,x,l,mid,num<<1);
if(R>mid)modify1(L,R,x,mid+1,r,num<<1|1);
up1(num);
}
int main(){
int i,Q,x,y,z,o,tmp,l,r,mid;LL gs0,gs1;bool co;
read(n);tot=1;
rep(i,2,n){
read(x);read(y);
add(x,y);add(y,x);
}
DFS1(1,0);DFS2(1);
build0(1,n,1);build1(1,n,1);
for(read(Q);Q--;){
read(o);read(x);
if(o){
gs0=query0(dfn[x],1,n,1);gs1=query1(dfn[x],1,n,1);
z=x;
if(x>1){
co=col[x=pre[x]];
if(col[z]){
modify0(dfn[x],dfn[x],gs0,1,n,1);
modify1(dfn[x],dfn[x],-gs1,1,n,1);
for(x=pre[x];x&&query2(dfn[y=dad[x]],dfn[x],1,n,1)==co;x=pre[y]){
if(!co)modify0(dfn[y],dfn[x],gs0,1,n,1);
else modify1(dfn[y],dfn[x],-gs1,1,n,1);
}
if(x){
for(l=dfn[y]+1,r=dfn[x];l<=r;){
mid=l+r>>1;
if(query2(mid,dfn[x],1,n,1)==co)
r=mid-1;
else l=mid+1;
}
if(!co)modify0(r,dfn[x],gs0,1,n,1);
else modify1(r,dfn[x],-gs1,1,n,1);
}
}
else{
modify0(dfn[x],dfn[x],-gs0,1,n,1);
modify1(dfn[x],dfn[x],gs1,1,n,1);
for(x=pre[x];x&&query2(dfn[y=dad[x]],dfn[x],1,n,1)==co;x=pre[y]){
if(!co)modify0(dfn[y],dfn[x],-gs0,1,n,1);
else modify1(dfn[y],dfn[x],gs1,1,n,1);
}
if(x){
for(l=dfn[y]+1,r=dfn[x];l<=r;){
mid=l+r>>1;
if(query2(mid,dfn[x],1,n,1)==co)
r=mid-1;
else l=mid+1;
}
if(!co)modify0(r,dfn[x],-gs0,1,n,1);
else modify1(r,dfn[x],gs1,1,n,1);
}
}
}
col[z]^=1;modify2(dfn[z],1,n,1);
}
else{
if(col[x]){
while(x&&query2(dfn[y=dad[x]],dfn[x],1,n,1)==1)x=pre[z=y];
if(!x){
printf("%d\n",query1(1,1,n,1));
continue;
}
for(l=dfn[y]+1,r=dfn[x];l<=r;){
mid=l+r>>1;
if(query2(mid,dfn[x],1,n,1)==1)
r=mid-1;
else l=mid+1;
}
if(l>dfn[x])printf("%d\n",query1(dfn[z],1,n,1));
else printf("%d\n",query1(l,1,n,1));
}
else{
while(x&&!query2(dfn[y=dad[x]],dfn[x],1,n,1))x=pre[z=y];
if(!x){
printf("%d\n",query0(1,1,n,1));
continue;
}
for(l=dfn[y]+1,r=dfn[x];l<=r;){
mid=l+r>>1;
if(!query2(mid,dfn[x],1,n,1))
r=mid-1;
else l=mid+1;
}
if(l>dfn[x])printf("%d\n",query0(dfn[z],1,n,1));
else printf("%d\n",query0(l,1,n,1));
}
}
}
return 0;
}