zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    173. Binary Search Tree Iterator
    199. Binary Tree Right Side View
    230. Kth Smallest Element in a BST
    236. Lowest Common Ancestor of a Binary Tree
    337. House Robber III
    449. Serialize and Deserialize BST
    508. Most Frequent Subtree Sum
    513. Find Bottom Left Tree Value
    129. Sum Root to Leaf Numbers
    652. Find Duplicate Subtrees
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9643115.html
Copyright © 2011-2022 走看看