BZOJ3637 Query on a tree VI(树链剖分+线段树)
考虑对于每一个点维护子树内与其连通的点的信息。为了换色需要,记录每个点黑白两种情况下子树内连通块的大小。
查询时,找到深度最浅的同色祖先即可,这可以比较简单的树剖+线段树乱搞一下(似乎就是qtree3),具体的,可以维护一下区间是否全黑/白,线段树上二分。换色会造成一个连通块分裂并产生新连通块,这只会影响到祖先节点的信息。同样树剖+线段树暴力改上去即可。
因为写的实在太丑没有一个oj能过,darkbzoj上42个点跑到第38个T掉了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 100010 int n,m,p[N],color[N],t=0; int dfn[N],id[N],top[N],fa[N],son[N],size[N],cnt=0; int L[N<<2],R[N<<2],tree[2][N<<2],lazy[2][N<<2],same[2][N<<2]; struct data{int to,nxt; }edge[N<<1]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} void dfs1(int k) { size[k]=1;color[k]=1; for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]) { fa[edge[i].to]=k; dfs1(edge[i].to); size[k]+=size[edge[i].to]; if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to; } } void dfs2(int k,int from) { id[k]=++cnt;dfn[cnt]=k; top[k]=from; if (son[k]) dfs2(son[k],from); for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=fa[k]&&edge[i].to!=son[k]) dfs2(edge[i].to,edge[i].to); } void build(int k,int l,int r) { L[k]=l,R[k]=r;same[1][k]=1; if (l==r){tree[1][k]=size[dfn[l]];tree[0][k]=1;return;} int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } void down(int k) { tree[0][k<<1]+=lazy[0][k],tree[0][k<<1|1]+=lazy[0][k]; tree[1][k<<1]+=lazy[1][k],tree[1][k<<1|1]+=lazy[1][k]; lazy[0][k<<1]+=lazy[0][k],lazy[0][k<<1|1]+=lazy[0][k]; lazy[1][k<<1]+=lazy[1][k],lazy[1][k<<1|1]+=lazy[1][k]; lazy[0][k]=lazy[1][k]=0; } int getsame(int k,int l,int r,int p) { if (L[k]==l&&R[k]==r) return same[p][k]; if (lazy[p][k]) down(k); int mid=L[k]+R[k]>>1; if (r<=mid) return getsame(k<<1,l,r,p); else if (l>mid) return getsame(k<<1|1,l,r,p); else return getsame(k<<1,l,mid,p)&getsame(k<<1|1,mid+1,r,p); } int query1(int k,int l,int r,int p) { if (L[k]==R[k]) return same[p][k]?l:0; if (lazy[p][k]) down(k); int mid=L[k]+R[k]>>1; if (r<=mid) return query1(k<<1,l,r,p); else if (l>mid) return query1(k<<1|1,l,r,p); else return getsame(k,mid,r,p)?query1(k<<1,l,mid,p):query1(k<<1|1,mid+1,r,p); } int queryance(int x,int p) { int ans=id[x]; while (1) { int y=query1(1,id[top[x]],id[x],p); if (!y) break; if (y>id[top[x]]) return y; ans=id[top[x]]; if (x==1) break; x=fa[top[x]]; } return ans; } int query(int k,int x,int p) { if (L[k]==R[k]) return tree[p][k]; if (lazy[p][k]) down(k); int mid=L[k]+R[k]>>1; if (x<=mid) return query(k<<1,x,p); else return query(k<<1|1,x,p); } void modify(int k,int l,int r,int x,int p) { if (L[k]==l&&R[k]==r) {tree[p][k]+=x,lazy[p][k]+=x;return;} if (lazy[p][k]) down(k); int mid=L[k]+R[k]>>1; if (r<=mid) modify(k<<1,l,r,x,p); else if (l>mid) modify(k<<1|1,l,r,x,p); else modify(k<<1,l,mid,x,p),modify(k<<1|1,mid+1,r,x,p); } void modifycolor(int k,int x,int p,int op) { if (L[k]==R[k]) {same[p][k]=op;return;} int mid=L[k]+R[k]>>1; if (x<=mid) modifycolor(k<<1,x,p,op); else modifycolor(k<<1|1,x,p,op); same[p][k]=same[p][k<<1]&&same[p][k<<1|1]; } void modifyance(int x,int p,int s,int y) { while (top[x]!=top[y]) { modify(1,id[top[x]],id[x],s,p); x=fa[top[x]]; } modify(1,id[y],id[x],s,p); } int main() { #ifndef ONLINE_JUDGE freopen("bzoj3637.in","r",stdin); freopen("bzoj3637.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<n;i++) { int x=read(),y=read(); addedge(x,y),addedge(y,x); } fa[1]=1;dfs1(1); dfs2(1,1); build(1,1,n); m=read(); while (m--) { int op=read(),x=read(),y=queryance(x,color[x]); if (op) { if (id[x]==y) { modifycolor(1,id[x],color[x],0); color[x]^=1; modifycolor(1,id[x],color[x],1); y=queryance(x,color[x]); if (x>1) modifyance(fa[x],color[x],query(1,id[x],color[x]),fa[dfn[y]]), modify(1,id[fa[x]],id[fa[x]],-query(1,id[x],color[x]^1),color[x]^1); } else { if (x>1) modifyance(fa[x],color[x],-query(1,id[x],color[x]),fa[dfn[y]]), modify(1,id[fa[x]],id[fa[x]],query(1,id[x],color[x]^1),color[x]^1); modifycolor(1,id[x],color[x],0); color[x]^=1; modifycolor(1,id[x],color[x],1); } } else printf("%d\n",query(1,y,color[x])); } return 0; }