• BZOJ2243: [SDOI2011]染色(树链剖分/LCT)


    Description

    给定一棵有n个节点的无根树和m个操作,操作有2类:
    1、将节点a到节点b路径上所有点都染成颜色c;
    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
    如“112221”由3段组成:“11”、“222”和“1”。
    请你写一个程序依次完成这m个操作。

    Input

    第一行包含2个整数n和m,分别表示节点数和操作数;
    第二行包含n个正整数表示n个节点的初始颜色
    下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
    下面 行每行描述一个操作:
    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

    Output

    对于每个询问操作,输出一行答案。

    Sample Input

    6 5
    2 2 1 2 1 1
    1 2
    1 3
    2 4
    2 5
    2 6
    Q 3 5
    C 2 1 1
    Q 3 5
    C 5 1 2
    Q 3 5

    Sample Output

    3
    1
    2

    解题思路:

    1.树链剖分:

    只修改链,不修改关系,树链剖分。

    线段树维护树链剖分序。

    时间复杂度O(nlogn2)

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll spc<<1
      5 #define rrr spc<<1|1
      6 using std::min;
      7 using std::max;
      8 using std::swap;
      9 struct trnt{
     10     int lc;
     11     int rc;
     12     int lzt;
     13     int val;
     14 }tr[1000000];
     15 struct pnt{
     16     int hd;
     17     int col;
     18     int mxs;
     19     int ind;
     20     int fa;
     21     int tp;
     22     int wgt;
     23     int dp;
     24 }p[1000000];
     25 struct ent{
     26     int twd;
     27     int lst;
     28 }e[1000000];
     29 struct bag{
     30     int cl;
     31     int cr;
     32     int vl;
     33     bag friend operator + (bag a,bag b)
     34     {
     35         if(!a.cl)
     36             a.cl=b.cl;
     37         if(!b.cr)
     38             b.cr=a.cr;
     39         return (bag){a.cl,b.cr,(a.vl+b.vl-(a.cr==b.cl)<0)?0:(a.vl+b.vl-(a.cr==b.cl))};
     40     }
     41 };
     42 int n,m;
     43 int cnt;
     44 int dfn;
     45 char cmd[10];
     46 void ade(int f,int t)
     47 {
     48     cnt++;
     49     e[cnt].twd=t;
     50     e[cnt].lst=p[f].hd;
     51     p[f].hd=cnt;
     52     return ;
     53 }
     54 void pushup(int spc)
     55 {
     56     tr[spc].lc=tr[lll].lc;
     57     tr[spc].rc=tr[rrr].rc;
     58     tr[spc].val=tr[lll].val+tr[rrr].val-(tr[lll].rc==tr[rrr].lc);
     59     return ;
     60 }
     61 void chg(int spc,int v)
     62 {
     63     tr[spc].val=1;
     64     tr[spc].lc=tr[spc].rc=v;
     65     tr[spc].lzt=v;
     66     return ;
     67 }
     68 void pushdown(int spc)
     69 {
     70     if(tr[spc].lzt)
     71     {
     72         chg(lll,tr[spc].lzt);
     73         chg(rrr,tr[spc].lzt);
     74         tr[spc].lzt=0;
     75     }
     76     return ;
     77 }
     78 void build(int l,int r,int pos,int spc,int v)
     79 {
     80     if(l==r)
     81     {
     82         tr[spc].lc=tr[spc].rc=v;
     83         tr[spc].val=1;
     84         tr[spc].lzt=0;
     85         return ;
     86     }
     87     int mid=(l+r)>>1;
     88     if(pos<=mid)
     89         build(l,mid,pos,lll,v);
     90     else
     91         build(mid+1,r,pos,rrr,v);
     92     pushup(spc);
     93     return ;
     94 }
     95 void Basic_dfs(int x,int f)
     96 {
     97     p[x].dp=p[f].dp+1;
     98     p[x].fa=f;
     99     int maxs=-1;
    100     p[x].wgt=1;
    101     for(int i=p[x].hd;i;i=e[i].lst)
    102     {
    103         int to=e[i].twd;
    104         if(to==f)
    105             continue;
    106         Basic_dfs(to,x);
    107         p[x].wgt+=p[to].wgt;
    108         if(p[to].wgt>maxs)
    109         {
    110             maxs=p[to].wgt;
    111             p[x].mxs=to;
    112         }
    113     }
    114     return ;
    115 }
    116 void Build_dfs(int x,int tpl)
    117 {
    118     if(!x)
    119         return ;
    120     p[x].tp=tpl;
    121     p[x].ind=++dfn;
    122     build(1,n,dfn,1,p[x].col);
    123     Build_dfs(p[x].mxs,tpl);
    124     for(int i=p[x].hd;i;i=e[i].lst)
    125     {
    126         int to=e[i].twd;
    127         if(p[to].ind)
    128             continue;
    129         Build_dfs(to,to);
    130     }
    131 }
    132 void update(int l,int r,int ll,int rr,int spc,int v)
    133 {
    134     if(ll>rr)
    135         return ;
    136     if(l>rr||ll>r)
    137         return ;
    138     pushdown(spc);
    139     if(ll<=l&&r<=rr)
    140     {
    141         chg(spc,v);
    142         return ;
    143     }
    144     int mid=(l+r)>>1;
    145     update(l,mid,ll,rr,lll,v);
    146     update(mid+1,r,ll,rr,rrr,v);
    147     pushup(spc);
    148     return ;
    149 }
    150 bag mk(int a,int b,int c)
    151 {
    152     return (bag){a,b,c};
    153 }
    154 bag ask(int l,int r,int ll,int rr,int spc)
    155 {
    156     if(l>rr||ll>r)
    157         return mk(0,0,0);
    158     pushdown(spc);
    159     if(ll<=l&&r<=rr)
    160         return mk(tr[spc].lc,tr[spc].rc,tr[spc].val);
    161     int mid=(l+r)>>1;
    162     return ask(l,mid,ll,rr,lll)+ask(mid+1,r,ll,rr,rrr);
    163 }
    164 int lca(int x,int y)
    165 {
    166     while(p[x].tp!=p[y].tp)
    167     {
    168         if(p[p[x].tp].dp<p[p[y].tp].dp)
    169             swap(x,y);
    170         x=p[p[x].tp].fa;
    171     }
    172     if(p[x].dp>p[y].dp)
    173         swap(x,y);
    174     return x;
    175 }
    176 void rvs(bag &a)
    177 {
    178     swap(a.cl,a.cr);
    179     return ;
    180 }
    181 int main()
    182 {
    183     scanf("%d%d",&n,&m);
    184     for(int i=1;i<=n;i++)
    185         scanf("%d",&p[i].col);
    186     for(int i=1;i<n;i++)
    187     {
    188         int a,b;
    189         scanf("%d%d",&a,&b);
    190         ade(a,b);
    191         ade(b,a);
    192     }
    193     Basic_dfs(1,0);
    194     Build_dfs(1,1);
    195     while(m--)
    196     {
    197         scanf("%s",cmd);
    198         if(cmd[0]=='C')
    199         {
    200             int a,b,c;
    201             scanf("%d%d%d",&a,&b,&c);
    202             int f=lca(a,b);
    203             while(p[a].tp!=p[f].tp)
    204             {
    205                 update(1,dfn,p[p[a].tp].ind,p[a].ind,1,c);
    206                 a=p[p[a].tp].fa;
    207             }
    208             update(1,dfn,p[f].ind,p[a].ind,1,c);
    209             a=b;
    210             while(p[a].tp!=p[f].tp)
    211             {
    212                 update(1,dfn,p[p[a].tp].ind,p[a].ind,1,c);
    213                 a=p[p[a].tp].fa;
    214             }
    215             update(1,dfn,p[f].ind,p[a].ind,1,c);
    216         }
    217         if(cmd[0]=='Q')
    218         {
    219             int a,b;
    220             
    221             scanf("%d%d",&a,&b);
    222             int f=lca(a,b);
    223             bag ans=(bag){0,0,0};
    224             while(p[a].tp!=p[f].tp)
    225             {
    226                 ans=ask(1,dfn,p[p[a].tp].ind,p[a].ind,1)+ans;
    227                 a=p[p[a].tp].fa;
    228             }
    229             if(a!=f)
    230                 ans=ask(1,dfn,p[f].ind+1,p[a].ind,1)+ans;
    231             bag ams=(bag){0,0,0};
    232             a=b;
    233             while(p[a].tp!=p[f].tp)
    234             {
    235                 ams=ask(1,dfn,p[p[a].tp].ind,p[a].ind,1)+ams;
    236                 a=p[p[a].tp].fa;
    237             }
    238             if(a!=f)
    239                 ams=ask(1,dfn,p[f].ind+1,p[a].ind,1)+ams;
    240             ans=ask(1,dfn,p[f].ind,p[f].ind,1)+ans;
    241             rvs(ans);
    242             ans=ans+ams;
    243             printf("%d
    ",ans.vl);
    244         }
    245     }
    246     return 0;
    247 }

    2.LCT:

    比较板子了。

    每次维护左侧颜色和右侧颜色(注意特判0节点值)

    反转时要反转左右颜色。

    路径提取一下输出答案就好了。

    时间复杂度O(nlogn)理论上比树剖快

    但是:

    蒟蒻的我:splay常数居然比logn大

    代码:

      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 using std::swap;
      9 struct trnt{
     10     int ch[2];
     11     int fa;
     12     int lzt;
     13     int chg;
     14     int sum;
     15     int val;
     16     int lc;
     17     int rc;
     18     int wgt;
     19     bool anc;
     20 }tr[1000000];
     21 int n,m;
     22 char cmd[10];
     23 bool whc(int spc)
     24 {
     25     return tr[tr[spc].fa].rs==spc;
     26 }
     27 void pushup(int spc)
     28 {
     29     tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1;
     30     tr[spc].sum=tr[lll].sum+tr[rrr].sum+1-(tr[lll].rc==tr[spc].val)-(tr[rrr].lc==tr[spc].val);
     31     tr[spc].lc=tr[lll].lc?tr[lll].lc:tr[spc].val;
     32     tr[spc].rc=tr[rrr].rc?tr[rrr].rc:tr[spc].val;
     33     return ;
     34 }
     35 void trr(int spc)
     36 {
     37     if(!spc)
     38         return ;
     39     swap(lll,rrr);
     40     swap(tr[spc].lc,tr[spc].rc);
     41     tr[spc].lzt^=1;
     42     return ;
     43 }
     44 void upd(int spc,int v)
     45 {
     46     if(!spc)
     47         return ;
     48     tr[spc].val=tr[spc].lc=tr[spc].rc=v;
     49     tr[spc].sum=1;
     50     tr[spc].chg=v;
     51     return ;
     52 }
     53 void pushdown(int spc)
     54 {
     55     if(tr[spc].lzt)
     56     {
     57         trr(lll);
     58         trr(rrr);
     59         tr[spc].lzt=0;
     60     }
     61     if(tr[spc].chg)
     62     {
     63         upd(lll,tr[spc].chg);
     64         upd(rrr,tr[spc].chg);
     65         tr[spc].chg=0;
     66     }
     67     return ;
     68 }
     69 void recal(int spc)
     70 {
     71     if(!tr[spc].anc)
     72         recal(tr[spc].fa);
     73     pushdown(spc);
     74     return ;
     75 }
     76 void rotate(int spc)
     77 {
     78     int f=tr[spc].fa;
     79     bool k=whc(spc);
     80     tr[f].ch[k]=tr[spc].ch[!k];
     81     tr[spc].ch[!k]=f;
     82     if(tr[f].anc)
     83     {
     84         tr[spc].anc=1;
     85         tr[f].anc=0;
     86     }else
     87         tr[tr[f].fa].ch[whc(f)]=spc;
     88     tr[spc].fa=tr[f].fa;
     89     tr[f].fa=spc;
     90     tr[tr[f].ch[k]].fa=f;
     91     pushup(f);
     92     pushup(spc);
     93     return ;
     94 }
     95 void splay(int spc)
     96 {
     97     recal(spc);
     98     while(!tr[spc].anc)
     99     {
    100         int f=tr[spc].fa;
    101         if(tr[f].anc)
    102         {
    103             rotate(spc);
    104             return ;
    105         }
    106         if(whc(spc)^whc(f))
    107             rotate(spc);
    108         else
    109             rotate(f);
    110         rotate(spc);
    111     }
    112     return ;
    113 }
    114 void access(int spc)
    115 {
    116     int lst=0;
    117     while(spc)
    118     {
    119         splay(spc);
    120         tr[rrr].anc=1;
    121         tr[lst].anc=0;
    122         rrr=lst;
    123         pushup(spc);
    124         lst=spc;
    125         spc=tr[spc].fa;
    126     }
    127     return ;
    128 }
    129 void Mtr(int spc)
    130 {
    131     access(spc);
    132     splay(spc);
    133     trr(spc);
    134     return ;
    135 }
    136 void split(int x,int y)
    137 {
    138     Mtr(x);
    139     access(y);
    140     splay(y);
    141     return ;
    142 }
    143 void link(int x,int y)
    144 {
    145     Mtr(x);
    146     tr[x].fa=y;
    147     return;
    148 }
    149 int main()
    150 {
    151     scanf("%d%d",&n,&m);
    152     for(int i=1;i<=n;i++)
    153     {
    154         tr[i].anc=1;
    155         scanf("%d",&tr[i].val);
    156         tr[i].lc=tr[i].rc=tr[i].val;
    157     }
    158     for(int i=1;i<n;i++)
    159     {
    160         int a,b;
    161         scanf("%d%d",&a,&b);
    162         link(a,b);
    163     }
    164     while(m--)
    165     {
    166         scanf("%s",cmd);
    167         if(cmd[0]=='Q')
    168         {
    169             int a,b;
    170             scanf("%d%d",&a,&b);
    171             split(a,b);
    172             printf("%d
    ",tr[b].sum);
    173         }else{
    174             int a,b,c;
    175             scanf("%d%d%d",&a,&b,&c);
    176             split(a,b);
    177             upd(b,c);
    178         }
    179     }
    180     return 0;
    181 }
  • 相关阅读:
    spring boot三种方式设置跨域
    完整卸载Mysql
    【OBIEE】OBIEE集成Echarts作图
    【OBIEE】BIEE培训(一)
    【Oracle】Oracle物化视图
    【Oracle】oracle11g安装过程提示swap size 检查失败问题
    【Linux】centOS7下安装GUI图形界面
    【Nginx】Linux环境搭建nginx负载
    【oracle】Oracle创建带参数视图
    抢票:搭建github最火的12306项目
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9643115.html
Copyright © 2020-2023  润新知