首页 > 代码库 > 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

树点涂色

Time Limit: 10 Sec  Memory Limit: 128 MB
[Submit][Status][Discuss]

Description

  Bob有一棵n个点的有根树,其中1号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
  1 x:
    把点x到根节点的路径上所有的点染上一种没有用过的新颜色。
  2 x y:
    求x到y的路径的权值。
  3 x:
    在以x为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
  Bob一共会进行m次操作

Input

  第一行两个数n,m。
  接下来n-1行,每行两个数a,b,表示a与b之间有一条边。
  接下来m行,表示操作,格式见题目描述。

Output

  每当出现2,3操作,输出一行。
  如果是2操作,输出一个数表示路径的权值
  如果是3操作,输出一个数表示权值的最大值

Sample Input

  5 6
  1 2
  2 3
  3 4
  3 5
  2 4 5
  3 3
  1 4
  2 4 5
  1 5
  2 4 5

Sample Output

  3
  4
  2
  2

HINT

  1<=n,m<=100000

Source

  我们将边两端的点颜色相同的边设为实边不同的设为虚边。那么一次新增颜色的操作显然就是LCTaccess操作!access的时候恰是虚边和实边的转换。

  那么我们只要用线段树维护每个点到根的贡献,结合dfs序来实现子树加,每次在LCT进行access的时候进行+-1修改,然后询问的时候用区间求和,区间最值求得答案即可。

Code

技术分享
  1 #include<iostream>    2 #include<string>    3 #include<algorithm>    4 #include<cstdio>    5 #include<cstring>    6 #include<cstdlib>    7 #include<cmath>  8 using namespace std;   9 typedef long long s64; 10   11 const int ONE = 2e5+5; 12   13 int n,m; 14 int x,y,P; 15 int POS[ONE],POSCNT; 16 int pos[ONE],dfn_cnt,size[ONE],dfn[ONE]; 17 int Dep[ONE],son[ONE],Top[ONE];  18 int lc[ONE],rc[ONE],fa[ONE],fat[ONE]; 19 int res_max,res_value; 20  21 inline int get()  22 { 23         int res=1,Q=1;  char c; 24         while( (c=getchar())<48 || c>57) 25         if(c==-)Q=-1; 26         if(Q) res=c-48;  27         while((c=getchar())>=48 && c<=57)  28         res=res*10+c-48;  29         return res*Q;  30 } 31  32 namespace tree 33 { 34         int next[ONE],first[ONE],go[ONE],tot=0; 35          36         void Add(int u,int v) 37         { 38             next[++tot]=first[u];    first[u]=tot;    go[tot]=v; 39             next[++tot]=first[v];    first[v]=tot;    go[tot]=u; 40         } 41          42         void Dfs(int u,int father) 43         { 44             pos[u] = ++dfn_cnt; dfn[dfn_cnt] = u; 45             size[u] = 1; 46             Dep[u] = Dep[father] + 1; 47             for(int e=first[u];e;e=next[e]) 48             { 49                 int v=go[e]; 50                 if(v==father) continue; 51                 fa[v] = u;    fat[v] = u; 52                 Dfs(v,u); 53                 size[u] += size[v]; 54                 if(size[v] > size[son[u]]) son[u] = v; 55             } 56         } 57          58         void Dfs_twice(int u,int father) 59         { 60             POS[u] = ++POSCNT; 61             if(son[u]) 62             { 63                 int v=son[u]; 64                 Top[v] = Top[u]; 65                 Dfs_twice(v,u); 66             } 67              68             for(int e=first[u];e;e=next[e]) 69             { 70                 int v=go[e]; 71                 if(v==father || v==son[u]) continue; 72                 Top[v] = v; 73                 Dfs_twice(v,u); 74             } 75         } 76          77         int LCA(int x,int y) 78         { 79             while(Top[x]!=Top[y]) 80             { 81                 if( Dep[Top[x]] < Dep[Top[y]] ) swap(x,y); 82                 x = fat[Top[x]]; 83             } 84             if(POS[x] > POS[y]) swap(x,y); 85             return x; 86         } 87 } 88  89 namespace Seg 90 { 91         struct power 92         { 93             int add,value; 94             int maxx; 95         }Node[ONE*4]; 96          97         void pushdown(int i,int Q) 98         { 99             if(Node[i].add)100             {101                 Node[i<<1].add += Node[i].add;102                 Node[i<<1|1].add += Node[i].add;103                 Node[i<<1].maxx += Node[i].add;104                 Node[i<<1|1].maxx += Node[i].add; 105                 Node[i<<1].value += Node[i].add * (Q-Q/2);106                 Node[i<<1|1].value += Node[i].add * (Q/2);107                 Node[i].add = 0;108             }109         }110         111         void Build(int i,int l,int r)112         {113             if(l==r)114             {115                 Node[i].value =http://www.mamicode.com/ Dep[dfn[l]];116                 Node[i].maxx = Dep[dfn[l]];117                 return ;118             }119             int mid = l+r>>1;120             Build(i<<1,l,mid);    Build(i<<1|1,mid+1,r);121             Node[i].value = http://www.mamicode.com/Node[i<<1].value + Node[i<<1|1].value;122             Node[i].maxx = max(Node[i<<1].maxx, Node[i<<1|1].maxx);123         }124         125         void Update(int i,int l,int r,int L,int R,int x)126         {127             if(L<=l && r<=R)128             {129                 Node[i].add += x;130                 Node[i].value += (r-l+1)*x;131                 Node[i].maxx += x;132                 return;133             }134             pushdown(i,r-l+1);135             int mid = l+r>>1;136             if(L<=mid) Update(i<<1,l,mid,L,R,x);137             if(mid+1<=R) Update(i<<1|1,mid+1,r,L,R,x);138             139             Node[i].value = http://www.mamicode.com/Node[i<<1].value + Node[i<<1|1].value;140             Node[i].maxx = max(Node[i<<1].maxx , Node[i<<1|1].maxx);141         }142         143         void Query(int i,int l,int r,int L,int R)144         {145             if(L<=l && r<=R)146             {147                 res_max = max(res_max,Node[i].maxx);148                 res_value += Node[i].value;149                 return;150             }151             pushdown(i,r-l+1);152             int mid = l+r>>1;153             if(L<=mid) Query(i<<1,l,mid,L,R);154             if(mid+1<=R) Query(i<<1|1,mid+1,r,L,R);155         }156 }157 158 namespace LCT159 {160         int is_real(int x)161         {162             return (lc[fa[x]]==x || rc[fa[x]]==x);163         }164     165         void Turn(int x)166         {167             int y = fa[x], z = fa[y];168             int b = x==lc[y] ? rc[x]:lc[x];169             170             fa[x] = z;    fa[y] = x;171             if(b) fa[b] = y;172             173             if(z)174             {175                 if(y == lc[z]) lc[z] = x;176                 else177                 if(y == rc[z]) rc[z] = x;178             }179             180             if(x==lc[y]) rc[x]=y,lc[y]=b;181             else lc[x]=y,rc[y]=b;182         }183         184         void Splay(int x)185         {186             while(is_real(x))187             {188                 if(is_real(fa[x]))189                 {190                     if( (lc[fa[x]]==x) == (lc[fa[fa[x]]]==fa[x])) Turn(fa[x]);191                     else Turn(x); 192                 }193                 Turn(x);194             }195         }196         197         int find_root(int x)198         {199             while(lc[x]) x=lc[x];200             return x;201         }202         203         void access(int x)204         {205             for(int p=x,q=0; p; q=p,p=fa[p])206             {207                 Splay(p);208                 if(rc[p])209                 {210                     int N = find_root(rc[p]);211                     Seg::Update(1,1,n,pos[N],pos[N]+size[N]-1,1);212                 }213                 214                 rc[p] = q;215                 if(rc[p])216                 {217                     int N = find_root(rc[p]);218                     Seg::Update(1,1,n,pos[N],pos[N]+size[N]-1,-1);219                 }220             }221         }222 }223 224 int Getsum(int x,int y)225 {226         int Ans, Sx, Sy, SLCA, LCA;227         LCA = tree::LCA(x,y);228         x=pos[x],    y=pos[y],    LCA=pos[LCA];229         res_value = http://www.mamicode.com/0;    Seg::Query(1,1,n,x,x);    Sx = res_value;230         res_value = http://www.mamicode.com/0;    Seg::Query(1,1,n,y,y);    Sy = res_value;231         res_value = http://www.mamicode.com/0;    Seg::Query(1,1,n,LCA,LCA);    SLCA = res_value;232         return Sx+Sy-2*SLCA+1;233 }234 235 int Getmax(int x)236 {237         res_max = 0;238         Seg::Query(1,1,n,pos[x],pos[x]+size[x]-1);239         return res_max;240 }241 242 int main()243 {244         n=get();    m=get();245         for(int i=1;i<=n-1;i++)246         {247             x=get();    y=get();248             tree::Add(x,y);249         }250         251         tree::Dfs(1,0);252         Top[1] = 1, tree::Dfs_twice(1,0);253         Seg::Build(1,1,n);254         255         while(m--)256         {257             P = get();    x=get();258             if(P==1)259                 LCT::access(x);260             if(P==2)261                 y=get(), printf("%d\n",Getsum(x,y));262             if(P==3)263                 printf("%d\n",Getmax(x));    264         }265 }
View Code

 

【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]