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:

  • 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.
  • 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

5
1 2
1 3
1 4
1 5
3
0 1
1 1
0 1

Sample Output

5
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 }
时间: 2024-08-13 12:37:17

bzoj3637: Query on a tree VI的相关文章

bzoj 3637: Query on a tree VI 树链剖分 &amp;&amp; AC600

3637: Query on a tree VI Time Limit: 8 Sec  Memory Limit: 1024 MBSubmit: 206  Solved: 38[Submit][Status][Discuss] Description You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are numbered from 1 to n. Each nod

bzoj3637 CodeChef SPOJ - QTREE6 Query on a tree VI 题解

题意: 一棵n个节点的树,节点有黑白两种颜色,初始均为白色.两种操作:1.更改一个节点的颜色;2.询问一个节点所处的颜色相同的联通块的大小. 思路: 1.每个节点记录仅考虑其子树时,假设其为黑色时所处的黑色联通块的大小和假设其为白色时所处的白色联通块的大小(树状数组维护). 2.查询时找到深度最小的.与该点颜色相同的且两点之间的点颜色均与这两点相同(两点可以重合)(不妨称它为最远祖先)的答案. 3.修改时应该修改该节点的父亲至最远祖先的父亲上的值. 4.用树链剖分和树状数组维护. 5.寻找最远祖

[BZOJ 3637]Query on a tree VI

偶然看见了这题,觉得自己 QTREE.COT 什么的都没有刷过的真是弱爆了…… 一道思路很巧妙的题,终于是在约大爷的耐心教导下会了,真是太感谢约大爷了. 这题显然是树链剖分,但是链上维护的东西很恶心.其核心思想是找到一个相连的最浅同色节点,那么我只要维护每个点的子树中与他相连的点的数量即可 用 f[c][u] 表示在 u 的子树中与 u 相连 (假设 u 无色) 且颜色为 c 的点数 查询直接算出与 u 相连的最浅同色节点 a,ans=f[c[u]][a] 考虑修改,我们发现每次 u 被反转,影

SPOJ 16549 - QTREE6 - Query on a tree VI 「一种维护树上颜色连通块的操作」

题意 有操作 $0$ $u$:询问有多少个节点 $v$ 满足路径 $u$ 到 $v$ 上所有节点(包括)都拥有相同的颜色$1$ $u$:翻转 $u$ 的颜色 题解 直接用一个 $LCT$ 去暴力删边连边显然会 $T$ 那么只有两个颜色的话就可以建两棵 $LCT$ ,观察到每次单点修改颜色时其子树所包含连通块在原颜色树上与其父亲所代表连通块断开,所以可以看作断开与父节点的边(实际上是点化边的思想),那么其它常规操作即可 注意要建个虚拟节点作为根节点的父亲 注意 $0$ 操作询问的输出,详细解释有在

[hdu 6191] Query on A Tree

Query on A Tree Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 733    Accepted Submission(s): 275 Problem Description Monkey A lives on a tree, he always plays on this tree. One day, monkey

2017广西邀请赛 Query on A Tree (可持续化字典树)

Query on A Tree 时间限制: 8 Sec  内存限制: 512 MB提交: 15  解决: 3[提交][状态][讨论版] 题目描述 Monkey A lives on a tree. He always plays on this tree.One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to pr

spoj 375 Query on a tree (树链剖分)

Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to ti or Q

【百度之星2014~复赛)解题报告】The Query on the Tree

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~复赛)解题报告]The Query on the Tree>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=673 前言

QTREE - Query on a tree

QTREE - Query on a tree 题目链接:http://www.spoj.com/problems/QTREE/ 参考博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html 树链剖分入门题 代码如下(附注解): 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define lson (x<<1) 5 #d