zoukankan      html  css  js  c++  java
  • 【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

    Solution

      我们将边两端的点颜色相同的边设为实边不同的设为虚边。那么一次新增颜色的操作显然就是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 = 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 = 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 = 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 LCT
    159 {
    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                 else
    177                 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 = 0;    Seg::Query(1,1,n,x,x);    Sx = res_value;
    230         res_value = 0;    Seg::Query(1,1,n,y,y);    Sy = res_value;
    231         res_value = 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
    ",Getsum(x,y));
    262             if(P==3)
    263                 printf("%d
    ",Getmax(x));    
    264         }
    265 }
    View Code
  • 相关阅读:
    玩转MySQL之Linux下的简单操作(服务启动与关闭、启动与关闭、查看版本)
    玩转MySQL之Linux下修改默认编码
    机器学习算法及应用领域相关的中国大牛
    [转载]Python 包管理工具解惑
    Vim常用操作和快捷键技巧总结
    [转载]那些C++牛人的博客
    [转载]学习c/c++的好网站
    [转载]C++内存管理
    [转载]SQL数据库如何加快查询速度
    [转载]Python3.x和Python2.x的区别
  • 原文地址:https://www.cnblogs.com/BearChild/p/6700013.html
Copyright © 2011-2022 走看看