zoukankan      html  css  js  c++  java
  • BZOJ4817: [Sdoi2017]树点涂色(LCT)

    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行,表示操作,格式见题目描述
    1<=n,m<=100000

    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

    解题思路:

    LCT好题access构造。

    将第一个操作视为access操作并更新答案。

    那么开始时视为没有轻重链。

    access过程中若发生轻重链转化时将子树答案都加1,并撤销上一节点操作。

    这样就可以在每一个节点上维护到根的权值和。

    第三问直接解决。

    第二问呢,发现合并两条链的代价就是两个链单独的代价-2*lca代价+1(因为lca节点需要考虑)

    子树修改普通Dfs就好了。

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll tr[spc].ch[0]
      5 #define rrr tr[spc].ch[1]
      6 #define ls ch[0]
      7 #define rs ch[1]
      8 typedef long long lnt;
      9 const int N=300000;
     10 struct seg_trnt{
     11     int lzt;
     12     int maxval;
     13 }ter[N<<2];
     14 struct spl_trnt{
     15     int ch[2];
     16     int fa;
     17     int lzt;
     18     bool anc;
     19 }tr[N];
     20 struct pnt{
     21     int hd;
     22     int dp;
     23     int ind;
     24     int oud;
     25     int fa[20];
     26 }p[N];
     27 struct ent{
     28     int twd;
     29     int lst;
     30 }e[N<<1];
     31 int n,m;
     32 int cnt;
     33 int dfn;
     34 bool sta=true;
     35 int pos[N];
     36 void pushup(int spc)
     37 {
     38     ter[spc].maxval=std::max(ter[spc<<1].maxval,ter[spc<<1|1].maxval);
     39     return ;
     40 }
     41 void ppushdown(int spc)
     42 {
     43     if(ter[spc].lzt)
     44     {
     45         ter[spc<<1].maxval+=ter[spc].lzt;
     46         ter[spc<<1|1].maxval+=ter[spc].lzt;
     47         ter[spc<<1].lzt+=ter[spc].lzt;
     48         ter[spc<<1|1].lzt+=ter[spc].lzt;
     49         ter[spc].lzt=0;
     50     }
     51     return ;
     52 }
     53 void update(int l,int r,int ll,int rr,int spc,int v)
     54 {
     55     if(ll>r||l>rr)
     56         return ;
     57     if(ll<=l&&r<=rr)
     58     {
     59         ter[spc].maxval+=v;
     60         ter[spc].lzt+=v;
     61         return ;
     62     }
     63     ppushdown(spc);
     64     int mid=(l+r)>>1;
     65     update(l,mid,ll,rr,spc<<1,v);
     66     update(mid+1,r,ll,rr,spc<<1|1,v);
     67     pushup(spc);
     68     return ;
     69 }
     70 int maxq(int l,int r,int ll,int rr,int spc)
     71 {
     72     if(ll>r||l>rr)
     73         return -0x3f3f3f3f;
     74     if(ll<=l&&r<=rr)
     75         return ter[spc].maxval;
     76     int mid=(l+r)>>1;
     77     ppushdown(spc);
     78     return std::max(maxq(l,mid,ll,rr,spc<<1),maxq(mid+1,r,ll,rr,spc<<1|1));
     79 }
     80 int query(int l,int r,int pos,int spc)
     81 {
     82     if(l==r)
     83         return ter[spc].maxval;
     84     ppushdown(spc);
     85     int mid=(l+r)>>1;
     86     if(pos<=mid)
     87         return query(l,mid,pos,spc<<1);
     88     return query(mid+1,r,pos,spc<<1|1);
     89 }
     90 void build(int l,int r,int spc)
     91 {
     92     if(l==r)
     93     {
     94         ter[spc].maxval=p[pos[l]].dp;
     95         return ;
     96     }
     97     int mid=(l+r)>>1;
     98     build(l,mid,spc<<1);
     99     build(mid+1,r,spc<<1|1);
    100     pushup(spc);
    101     return ;
    102 }
    103 void ade(int f,int t)
    104 {
    105     cnt++;
    106     e[cnt].twd=t;
    107     e[cnt].lst=p[f].hd;
    108     p[f].hd=cnt;
    109     return ;
    110 }
    111 void dfs(int x,int f)
    112 {
    113     p[x].dp=p[f].dp+1;
    114     p[x].fa[0]=f;
    115     pos[++dfn]=x;
    116     p[x].ind=dfn;
    117     for(int i=1;i<=19;i++)
    118         p[x].fa[i]=p[p[x].fa[i-1]].fa[i-1];
    119     for(int i=p[x].hd;i;i=e[i].lst)
    120     {
    121         int to=e[i].twd;
    122         if(to==f)
    123             continue;
    124         tr[to].fa=x;
    125         dfs(to,x);
    126     }
    127     p[x].oud=dfn;
    128     return ;
    129 }
    130 int Lca(int x,int y)
    131 {
    132     if(p[x].dp<p[y].dp)
    133         std::swap(x,y);
    134     for(int i=19;i>=0;i--)
    135     {
    136         if(p[p[x].fa[i]].dp>=p[y].dp)
    137             x=p[x].fa[i];
    138     }
    139     if(x==y)
    140         return x;
    141     for(int i=19;i>=0;i--)
    142     {
    143         if(p[x].fa[i]!=p[y].fa[i])
    144             x=p[x].fa[i],y=p[y].fa[i];
    145     }
    146     return p[x].fa[0];
    147 }
    148 bool whc(int spc)
    149 {
    150     return tr[tr[spc].fa].rs==spc;
    151 }
    152 void trr(int spc)
    153 {
    154     if(!spc)
    155         return ;
    156     std::swap(lll,rrr);
    157     tr[spc].lzt^=1;
    158     return ;
    159 }
    160 void pushdown(int spc)
    161 {
    162     if(tr[spc].lzt)
    163     {
    164         tr[spc].lzt=0;
    165         trr(lll);
    166         trr(rrr);
    167     }
    168     return ;
    169 }
    170 void recal(int spc)
    171 {
    172     if(!tr[spc].anc)
    173         recal(tr[spc].fa);
    174     pushdown(spc);
    175     return ;
    176 }
    177 void rotate(int spc)
    178 {
    179     int f=tr[spc].fa;
    180     bool k=whc(spc);
    181     tr[f].ch[k]=tr[spc].ch[!k];
    182     tr[spc].ch[!k]=f;
    183     if(tr[f].anc)
    184     {
    185         tr[f].anc=0;
    186         tr[spc].anc=1;
    187     }else
    188         tr[tr[f].fa].ch[whc(f)]=spc;
    189     tr[spc].fa=tr[f].fa;
    190     tr[f].fa=spc;
    191     tr[tr[f].ch[k]].fa=f;
    192     return ;
    193 }
    194 void splay(int spc)
    195 {
    196     recal(spc);
    197     while(!tr[spc].anc)
    198     {
    199         int f=tr[spc].fa;
    200         if(tr[f].anc)
    201         {
    202             rotate(spc);
    203             return ;
    204         }
    205         if(whc(spc)^whc(f))
    206             rotate(spc);
    207         else
    208             rotate(f);
    209         rotate(spc);
    210     }
    211     return ;
    212 }
    213 int leftpos(int spc)
    214 {
    215     pushdown(spc);
    216     while(lll)
    217     {
    218         spc=lll;
    219         pushdown(spc);
    220     }
    221     return spc;
    222 }
    223 void access(int spc)
    224 {
    225     int lst=0,x;
    226     while(spc)
    227     {
    228         splay(spc);
    229         tr[lst].anc=0;
    230         tr[rrr].anc=1;
    231         x=leftpos(rrr);
    232         if(x&&!sta)
    233             update(1,n,p[x].ind,p[x].oud,1,1);
    234         x=leftpos(lst);
    235         if(x&&!sta)
    236             update(1,n,p[x].ind,p[x].oud,1,-1);
    237         rrr=lst;
    238         lst=spc;
    239         spc=tr[spc].fa;
    240     }
    241     return ;
    242 }
    243 void Mtr(int spc)
    244 {
    245     access(spc);
    246     splay(spc);
    247     trr(spc);
    248     return ;
    249 }
    250 void split(int x,int y)
    251 {
    252     Mtr(x);
    253     access(y);
    254     splay(y);
    255     return ;
    256 }
    257 void link(int x,int y)
    258 {
    259     split(x,y);
    260     tr[x].fa=y;
    261     return ;
    262 }
    263 int main()
    264 {
    265     scanf("%d%d",&n,&m);
    266     for(int i=1;i<=n;i++)
    267     {
    268         tr[i].anc=true;
    269     }
    270     for(int i=1;i<n;i++)
    271     {
    272         int a,b;
    273         scanf("%d%d",&a,&b);
    274         ade(a,b);
    275         ade(b,a);
    276     }
    277     dfs(1,1);
    278     build(1,n,1);
    279     sta=false;
    280     while(m--)
    281     {
    282         int cmd;
    283         scanf("%d",&cmd);
    284         if(cmd==1)
    285         {
    286             int x;
    287             scanf("%d",&x);
    288             Mtr(1);
    289             access(x);
    290         }else if(cmd==2)
    291         {
    292             int ans=1;
    293             int x,y;
    294             scanf("%d%d",&x,&y);
    295             int z=Lca(x,y);
    296             ans+=query(1,n,p[x].ind,1);
    297             ans+=query(1,n,p[y].ind,1);
    298             ans-=query(1,n,p[z].ind,1)<<1;
    299             printf("%d
    ",ans);
    300         }else{
    301             int x;
    302             scanf("%d",&x);
    303             printf("%d
    ",maxq(1,n,p[x].ind,p[x].oud,1));
    304         }
    305     }
    306     return 0;
    307 }
  • 相关阅读:
    NOIP模拟题 管道
    NOIP模拟题 序列
    NOIP模拟题 栅栏
    NOIP模拟题 斐波那契数列
    CodeForces 797F Mice and Holes
    CodeForces 589H Tourist Guide
    CERC2016 爵士之旅 Jazz Journey
    BZOJ3832 Rally
    BZOJ1061 NOI2008 志愿者招募
    js数组的操作
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10116447.html
Copyright © 2011-2022 走看看