bzoj3637: Query on a tree VI
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3637: Query on a tree VI相关的知识,希望对你有一定的参考价值。
Description
You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are numbered from 1 to n.
Each node has a color, white or black. All the nodes are black initially.
We will ask you to perfrom some instructions of the following form:
- 0 u : ask for how many nodes are connected to u, two nodes are connected iff all the node on the path from u to v (inclusive u and v) have a same color.
- 1 u : toggle the color of u(that is, from black to white, or from white to black).
Input
The first line contains a number n denoted how many nodes in the tree(1 ≤ n ≤ 105). The next n - 1 lines, each line has two numbers (u, v) describe a edge of the tree(1 ≤ u, v ≤ n). The next line contains a number m denoted how many operations we are going to process(1 ≤ m ≤ 105). The next m lines, each line describe a operation (t, u) as we mentioned above(0 ≤ t ≤ 1, 1 ≤ u ≤ n).
Output
For each query operation, output the corresponding result.
Sample Input
1 2
1 3
1 4
1 5
3
0 1
1 1
0 1
Sample Output
1
题解:
先将树定个根,然后建立黑白两棵lct
对于黑树,时刻满足如果有边u-v,则v一定是黑点(u不一定是黑点)
且对于黑树上的某个点,记录一下通过虚边和它相连的黑点有多少,lct上维护这条链的总和,白树同理
对于单点改色,假如它是黑点,要在黑树上把它和它父亲节点断开,然后再在白树上把它和它父亲节点连起来,白点同理
对于单点查询,假如它是黑点,把它access上去后要判断这条链最上面的那个点是不是黑点,不是就要输出最上面那个点的儿子节点,白点同理
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 char ch; 8 bool ok; 9 void read(int &x){ 10 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1; 11 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar()); 12 if (ok) x=-x; 13 } 14 const int maxn=100005; 15 const int maxm=200005; 16 int n,q,op,a,b,tot,now[maxn],son[maxm],pre[maxm],col[maxn],fa[maxn]; 17 bool flag[maxn]; 18 struct LCT{ 19 int id,fa[maxn],son[maxn][2],tot[maxn],sum[maxn]; 20 void init(int x,int op){tot[x]+=op,sum[x]+=op;} 21 int which(int x){return son[fa[x]][1]==x;} 22 bool isroot(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;} 23 void update(int x){ 24 sum[x]=tot[x]; 25 if (son[x][0]) sum[x]+=sum[son[x][0]]; 26 if (son[x][1]) sum[x]+=sum[son[x][1]]; 27 } 28 void rotate(int x){ 29 int y=fa[x],z=fa[y],d=which(x),dd=which(y); 30 fa[son[x][d^1]]=y,son[y][d]=son[x][d^1],fa[x]=fa[y]; 31 if (!isroot(y)) son[z][dd]=x; 32 fa[y]=x,son[x][d^1]=y,update(y),update(x); 33 } 34 void splay(int x){ 35 while (!isroot(x)){ 36 if (isroot(fa[x])) rotate(x); 37 else if (which(fa[x])==which(x)) rotate(fa[x]),rotate(x); 38 else rotate(x),rotate(x); 39 } 40 } 41 void access(int x){ 42 for (int p=0;x;x=fa[x]){ 43 splay(x); 44 if (son[x][1]) tot[x]+=sum[son[x][1]]; 45 if (p) tot[x]-=sum[p]; 46 son[x][1]=p,update(p=x); 47 } 48 } 49 void cut(int x,int y){ 50 if (!y) return; 51 access(x),splay(x),fa[son[x][0]]=0,son[x][0]=0,update(x); 52 } 53 void link(int x,int y){ 54 if (!y) return; 55 access(y),splay(y),splay(x),fa[x]=y,son[y][1]=x,update(y); 56 } 57 int find_left(int x){for (access(x),splay(x);son[x][0];x=son[x][0]); return x;} 58 void query(int x){ 59 int t=find_left(x); splay(t); 60 printf("%d\n",col[t]==id?sum[t]:sum[son[t][1]]); 61 } 62 }T[2]; 63 void put(int a,int b){pre[++tot]=now[a],now[a]=tot,son[tot]=b;} 64 void add(int a,int b){put(a,b),put(b,a);} 65 void dfs(int u){ 66 for (int p=now[u],v=son[p];p;p=pre[p],v=son[p]) 67 if (v!=fa[u]) fa[v]=u,T[1].link(v,u),dfs(v); 68 } 69 int main(){ 70 read(n),T[0].id=0,T[1].id=1; 71 for (int i=1;i<n;i++) read(a),read(b),add(a,b); 72 for (int i=1;i<=n;i++) col[i]=1; 73 for (int i=1;i<=n;i++) T[1].init(i,1); 74 dfs(1); 75 for (read(q);q;q--){ 76 read(op),read(a); 77 if (op) T[col[a]].cut(a,fa[a]),T[col[a]].init(a,-1),col[a]^=1,T[col[a]].init(a,1),T[col[a]].link(a,fa[a]); 78 else T[col[a]].query(a); 79 } 80 return 0; 81 }
以上是关于bzoj3637: Query on a tree VI的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3637 CodeChef SPOJ - QTREE6 Query on a tree VI 题解
BZOJ1803Spoj1487 Query on a tree III 主席树+DFS序