[CodeChef-QTREE6]Query on a tree VI

题目大意:
  给你一棵黑白树,每个点默认是白色,要求支持以下两种操作:
    1.改变一个点的颜色;
    2.除去连接不同颜色的点的边,求某个点连通块的大小。

思路:
  对原树维护两个树链剖分,
  一棵维护当点x为白色时,以它为根结点的白色的子树大小;
  另一棵维护当点x为黑色时,以它为根结点的黑色的子树大小。(两者均不考虑x的实际颜色)
  方便起见,这里我们用q表示同一个连通分量中,深度最浅的祖先。
  询问一个点时,相当于在询问q的值。
  修改一个点时,相当于在原来颜色的树剖上将x到q的路径上的所有点同时减去x同色子树的大小,然后在新的颜色的树剖上将x到q路径上的所有点同时加上x同色子树的大小。
  如果对每个点都加/减显然不方便,因此我们可以用一些数据结构(线段树/树状数组)来维护差分。
  注意这道题会卡常,要么对每一条链建线段树,要么就用树状数组。
  接下来的问题是如何找到祖先q。
  如果暴力往上找,时间复杂度是O(n)的,显然会TLE。
  假如我们能够直接判断某一个树链上的点是否是同一种颜色,那就可以直接往上跳了。
  如何直接判断?
  考虑用0代表白色,1代表黑色,如果当这条链上所有点的权值和等于这条链上结点的个数,或等于0,那么肯定是同一种颜色的。
  这样我们可以直接维护树上前缀和,询问的时候减一下就可以了。
  最后还剩半条链没法跳的时候可以二分中间的结点。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<vector>
  4 inline int getint() {
  5     char ch;
  6     while(!isdigit(ch=getchar()));
  7     int x=ch^'0';
  8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
  9     return x;
 10 }
 11 const int V=100001;
 12 std::vector<int> e[V];
 13 inline void add_edge(const int &u,const int &v) {
 14     e[u].push_back(v);
 15 }
 16 int par[V],size[V],son[V],top[V],id[V],dep[V],id2[V],n;
 17 bool col[V];
 18 void dfs1(const int &x,const int &p) {
 19     par[x]=p;
 20     size[x]=1;
 21     dep[x]=dep[p]+1;
 22     for(unsigned i=0;i<e[x].size();i++) {
 23         const int &y=e[x][i];
 24         if(y==p) continue;
 25         dfs1(y,x);
 26         size[x]+=size[y];
 27         if(size[y]>size[son[x]]) {
 28             son[x]=y;
 29         }
 30     }
 31 }
 32 void dfs2(const int &x) {
 33     id[x]=++n;
 34     id2[n]=x;
 35     top[x]=x==son[par[x]]?top[par[x]]:x;
 36     if(son[x]) dfs2(son[x]);
 37     for(unsigned i=0;i<e[x].size();i++) {
 38         const int &y=e[x][i];
 39         if(y==par[x]||y==son[x]) continue;
 40         dfs2(y);
 41     }
 42 }
 43 class FenwickTree {
 44     private:
 45         int val[V];
 46         int lowbit(const int &x) {
 47             return x&-x;
 48         }
 49     public:
 50         void modify(int p,const int &x) {
 51             while(p<=n) {
 52                 val[p]+=x;
 53                 p+=lowbit(p);
 54             }
 55         }
 56         int query(int p) {
 57             int ret=0;
 58             while(p) {
 59                 ret+=val[p];
 60                 p-=lowbit(p);
 61             }
 62             return ret;
 63         }
 64 };
 65 FenwickTree t[3];
 66 bool check(const int &u,const int &m) {
 67     return t[2].query(id[u])-t[2].query(id[m]-1)==col[u]*(dep[u]-dep[m]+1);
 68 }
 69 inline int get_anc(int u) {
 70     while(top[u]!=1&&check(u,top[u])) {
 71         if(col[par[top[u]]]==col[u]) {
 72             u=par[top[u]];
 73         } else {
 74             return top[u];
 75         }
 76     }
 77     int l=id[top[u]],r=id[u];
 78     while(l<=r) {
 79         const int mid=(l+r)>>1;
 80         if(check(u,id2[mid])) {
 81             r=mid-1;
 82         } else {
 83             l=mid+1;
 84         }
 85     }
 86     return id2[r+1];
 87 }
 88 inline void modify2(int x,int y,const int &k,const bool &c) {
 89     while(top[x]!=top[y]) {
 90         t[c].modify(id[top[x]],k);
 91         t[c].modify(id[x]+1,-k);
 92         x=par[top[x]];
 93     }
 94     t[c].modify(id[y],k);
 95     t[c].modify(id[x]+1,-k);
 96 }
 97 inline void modify(const int &u) {
 98     if(u!=1) modify2(par[u],par[get_anc(u)],-t[col[u]].query(id[u]),col[u]);
 99     t[2].modify(id[u],col[u]?-1:1);
100     col[u]^=true;
101     if(u!=1) modify2(par[u],par[get_anc(u)],t[col[u]].query(id[u]),col[u]);
102 }
103 inline int query(const int &u) {
104     return t[col[u]].query(id[get_anc(u)]);
105 }
106 int main() {
107     int n=getint();
108     for(register int i=1;i<n;i++) {
109         const int u=getint(),v=getint();
110         add_edge(u,v);
111         add_edge(v,u);
112     }
113     dfs1(1,1);
114     dfs2(1);
115     for(register int i=1;i<=n;i++) {
116         t[0].modify(id[i],size[i]);
117         t[0].modify(id[i]+1,-size[i]);
118     }
119     t[1].modify(1,1);
120     for(register int m=getint();m;m--) {
121         const int t=getint(),u=getint();
122         if(t) {
123             modify(u);
124         } else {
125             printf("%d\n",query(u));
126         }
127     }
128     return 0;
129 }

 

posted @ 2017-09-20 10:11  skylee03  阅读(114)  评论(0编辑  收藏  举报