• BZOJ 2243: [SDOI2011]染色(树剖||LCT)


    题目链接:BZOJ 2243: [SDOI2011]染色

    题意:

    给你一棵树,每个点有个颜色,有两个操作。

    1 询问一条路径有多少段颜色。

    2 将一条路径全部染成一个颜色。

    题解:

    这题可以用树剖+线段树维护。

    但是LCT超级好写。

    要注意的就是rev那里要把左右颜色也要换一换。

     1 #include<bits/stdc++.h>
     2 #define F(i,a,b) for(int i=a;i<=b;i++)
     3 #define mst(a,b) memset(a,b,sizeof(a))
     4 using namespace std;
     5 
     6 namespace LCT
     7 {
     8     const int N=1e5+7;
     9     int f[N],son[N][2],val[N],sum[N],tmp[N],lazy[N],lc[N],rc[N];
    10     int g[N],v[N*2],nxt[N*2],ed;bool rev[N];
    11     void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;}
    12     void build(int x=1){
    13         sum[x]=val[x];
    14         for(int i=g[x];i;i=nxt[i])
    15             if(!f[v[i]]&&v[i]!=1)f[v[i]]=x,build(v[i]);    
    16     }
    17     bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
    18     void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]),swap(lc[x],rc[x]);rev[x]^=1;}
    19     void add(int x,int c){if(!x)return;sum[x]=1;val[x]=lazy[x]=lc[x]=rc[x]=c;}
    20     void pb(int x){
    21         if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;
    22         if(lazy[x])add(son[x][0],lazy[x]),add(son[x][1],lazy[x]),lazy[x]=0;
    23     }
    24     void up(int x){
    25         sum[x]=1,lc[x]=rc[x]=val[x];
    26         if(son[x][0])sum[x]+=sum[son[x][0]]-(val[x]==rc[son[x][0]]),lc[x]=lc[son[x][0]];
    27         if(son[x][1])sum[x]+=sum[son[x][1]]-(val[x]==lc[son[x][1]]),rc[x]=rc[son[x][1]];
    28     }
    29     void rotate(int x){
    30         int y=f[x],w=son[y][1]==x;
    31         son[y][w]=son[x][w^1];
    32         if(son[x][w^1])f[son[x][w^1]]=y;
    33         if(f[y]){
    34             int z=f[y];
    35             if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
    36         }
    37         f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
    38     }
    39     void splay(int x){
    40         int s=1,i=x,y;tmp[1]=i;
    41         while(!isroot(i))tmp[++s]=i=f[i];
    42         while(s)pb(tmp[s--]);
    43         while(!isroot(x)){
    44             y=f[x];
    45             if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
    46             rotate(x);
    47         }
    48         up(x);
    49     }
    50     void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
    51     int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
    52     void makeroot(int x){access(x);splay(x);rev1(x);}
    53     void link(int x,int y){makeroot(x);f[x]=y;access(x);}
    54     void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);}
    55     void cut(int x,int y){makeroot(x);cutf(y);}
    56     void update(int x,int y,int c){makeroot(x),access(y),splay(y),add(y,c);}
    57     int ask(int x,int y){makeroot(x);access(y);splay(y);return sum[y];}
    58 }
    59 
    60 using namespace LCT;
    61 int n,m,x,y,c;
    62 char op[3];
    63 
    64 int main()
    65 {
    66     scanf("%d%d",&n,&m);
    67     F(i,1,n)scanf("%d",val+i),val[i]++;
    68     F(i,2,n)
    69     {
    70         scanf("%d%d",&x,&y);
    71         adg(x,y),adg(y,x);
    72     }
    73     build();
    74     F(i,1,m)
    75     {
    76         scanf("%s",op);
    77         if(*op=='Q')
    78         {
    79             scanf("%d%d",&x,&y);
    80             printf("%d
    ",ask(x,y));
    81         }
    82         else if(*op=='C')
    83         {
    84             scanf("%d%d%d",&x,&y,&c);c++;
    85             update(x,y,c);
    86         }
    87     }
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    Layui表格之动态添加数据(表格多选解决方案)
    Ztree勾选节点后取消勾选其父子节点
    如何判断某个元素在页面上是否存在
    Linux环境搭建SVN服务
    Linux环境下验证码不显示F12报500
    Ztree节点前加上两个自定义按钮
    解决window.location.href参数太长
    Ztree加载完成默认选中根节点右侧生成表格
    输入框点击下滑Ztree菜单
    Mybatis中and和or的细节处理
  • 原文地址:https://www.cnblogs.com/bin-gege/p/7695094.html
Copyright © 2020-2023  润新知