• bzoj 2243 树链剖分


    2013-11-19 16:21

    原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243

    树链剖分,用线段树记录该区间的颜色段数,左右端点颜色数,然后就OK了

      1 //By BLADEVIL
      2 type
      3     rec                                 =record
      4         sum, left, right, succ, pred    :longint;
      5         lazy                            :longint;
      6     end;
      7      
      8 var
      9     n                                   :longint;
     10     pre, other                          :array[0..2000100] of longint;
     11     last                                :array[0..1000100] of longint;
     12     m                                   :longint;
     13     color                               :array[0..1000100] of longint;
     14     father, size, max_son               :array[0..1000100] of longint;
     15     dep, top, a, num                    :array[0..1000100] of longint;
     16     tot                                 :longint;
     17     flag                                :array[0..1000100] of boolean;
     18     l                                   :longint;
     19     t                                   :array[0..4000100] of rec;
     20      
     21 procedure swap(var a,b:longint);
     22 var
     23     c                                   :longint;
     24 begin
     25     c:=a; a:=b; b:=c;
     26 end;
     27      
     28 procedure connect(x,y:longint);
     29 begin
     30     inc(l);
     31     pre[l]:=last[x];
     32     last[x]:=l;
     33     other[l]:=y;
     34 end;
     35  
     36 procedure dfs(x:longint);
     37 var
     38     q, p                                :longint;
     39 begin
     40     size[x]:=1;
     41     q:=last[x];
     42     while q<>0 do
     43     begin
     44         p:=other[q];
     45         if not flag[p] then
     46         begin
     47             father[p]:=x;
     48             flag[p]:=true;
     49             dfs(p);
     50             inc(size[x],size[p]);
     51             if size[max_son[x]]<size[p] then max_son[x]:=p;
     52         end;
     53         q:=pre[q];
     54     end;
     55 end;
     56  
     57 procedure make(x,t,depth:longint);
     58 var
     59     q, p                                :longint;
     60 begin
     61     inc(tot);
     62     num[x]:=tot;
     63     top[x]:=t;
     64     a[tot]:=color[x];
     65     dep[x]:=depth;
     66     if (max_son[x]<>0) and (not flag[max_son[x]]) then
     67     begin
     68         flag[max_son[x]]:=true;
     69         make(max_son[x],t,depth);
     70     end;
     71     q:=last[x];
     72     while q<>0 do
     73     begin
     74         p:=other[q];
     75         if not flag[p] then
     76         begin
     77             flag[p]:=true;
     78             make(p,p,depth+1);
     79         end;
     80         q:=pre[q];
     81     end;
     82 end;
     83      
     84 procedure build(x,l,r:longint);
     85 var
     86     mid                                 :longint;
     87 begin
     88     t[x].left:=l; t[x].right:=r;
     89     if l=r then
     90     begin
     91         t[x].sum:=1;
     92         t[x].succ:=a[l];
     93         t[x].pred:=a[l];
     94         exit;
     95     end;
     96     mid:=(l+r) div 2;
     97     build(x*2,l,mid);
     98     build(x*2+1,mid+1,r);
     99     t[x].succ:=t[x*2].succ;
    100     t[x].pred:=t[x*2+1].pred;
    101     if t[x*2].pred=t[x*2+1].succ then
    102         t[x].sum:=t[x*2].sum+t[x*2+1].sum-1 else
    103         t[x].sum:=t[x*2].sum+t[x*2+1].sum;
    104 end;    
    105      
    106 procedure init;
    107 var
    108     i                                   :longint;
    109     x, y                                :longint;
    110      
    111 begin
    112     read(n,m);
    113     for i:=1 to n do read(color[i]);
    114     for i:=1 to n-1 do
    115     begin
    116         read(x,y);
    117         connect(x,y);
    118         connect(y,x);
    119     end;
    120     flag[1]:=true;
    121     dfs(1);
    122     fillchar(flag,sizeof(flag),false);
    123     flag[1]:=true;
    124     make(1,1,1);
    125     build(1,1,n);
    126 end;
    127  
    128 procedure change(x,l,r,z:longint);
    129 var
    130     mid                                 :longint;
    131 begin
    132     if t[x].lazy<>0 then
    133     begin
    134 t[x*2].lazy:=t[x].lazy;
    135         t[x*2].sum:=1;
    136         t[x*2].succ:=t[x].lazy;
    137         t[x*2].pred:=t[x].lazy;
    138         t[x*2+1].lazy:=t[x].lazy;
    139         t[x*2+1].sum:=1;
    140         t[x*2+1].succ:=t[x].lazy;
    141         t[x*2+1].pred:=t[x].lazy;
    142         t[x].lazy:=0;
    143     end;
    144     if (t[x].left=l) and (t[x].right=r) then
    145     begin
    146         t[x].lazy:=z;
    147         t[x].sum:=1;
    148         t[x].succ:=z;
    149         t[x].pred:=z;
    150         exit;
    151     end;
    152     with t[x] do mid:=(left+right) div 2;
    153     if mid<l then change(x*2+1,l,r,z) else
    154     if mid>=r then change(x*2,l,r,z) else
    155     begin
    156         change(x*2,l,mid,z);
    157         change(x*2+1,mid+1,r,z);
    158     end;
    159     t[x].succ:=t[x*2].succ;
    160     t[x].pred:=t[x*2+1].pred;
    161     if t[x*2].pred=t[x*2+1].succ then
    162         t[x].sum:=t[x*2].sum+t[x*2+1].sum-1 else
    163         t[x].sum:=t[x*2].sum+t[x*2+1].sum;
    164 end;
    165  
    166 function ask(x,l,r:longint):rec;
    167 var
    168     mid                                 :longint;
    169 t1, t2     :rec;
    170 begin
    171     if t[x].lazy<>0 then
    172     begin
    173         t[x*2].lazy:=t[x].lazy;
    174         t[x*2].sum:=1;
    175         t[x*2].succ:=t[x].lazy;
    176         t[x*2].pred:=t[x].lazy;
    177         t[x*2+1].lazy:=t[x].lazy;
    178         t[x*2+1].sum:=1;
    179         t[x*2+1].succ:=t[x].lazy;
    180         t[x*2+1].pred:=t[x].lazy;
    181         t[x].lazy:=0;
    182     end;
    183      
    184     if (t[x].left=l) and (t[x].right=r) then
    185     begin
    186         ask.succ:=t[x].succ;
    187         ask.pred:=t[x].pred;
    188         ask.sum:=t[x].sum;
    189         exit;
    190     end;
    191      
    192     with t[x] do mid:=(left+right) div 2;
    193     if mid<l then
    194     begin
    195 t2:=ask(x*2+1,l,r);
    196         ask.succ:=t2.succ;
    197         ask.pred:=t2.pred;
    198         ask.sum:=t2.sum
    199     end else
    200     if mid>=r then
    201     begin
    202 t1:=ask(x*2,l,r);
    203         ask.succ:=t1.succ;
    204         ask.pred:=t1.pred;
    205         ask.sum:=t1.sum
    206     end else
    207     begin
    208 t1:=ask(x*2,l,mid); 
    209 t2:=ask(x*2+1,mid+1,r);
    210         ask.succ:=t1.succ;
    211         ask.pred:=t2.pred;
    212         if t1.pred=t2.succ then
    213             ask.sum:=t1.sum+t2.sum-1 else
    214             ask.sum:=t1.sum+t2.sum;
    215     end;
    216 end;
    217  
    218 procedure paint(x,y,z:longint);
    219 begin
    220     if dep[x]>dep[y] then swap(x,y);
    221     while dep[x]<dep[y] do
    222     begin
    223         change(1,num[top[y]],num[y],z);
    224         y:=father[top[y]];
    225     end;
    226     while top[x]<>top[y] do
    227     begin
    228         change(1,num[top[x]],num[x],z);
    229         change(1,num[top[y]],num[y],z);
    230         x:=father[top[x]];
    231         y:=father[top[y]];
    232     end;
    233     x:=num[x];
    234     y:=num[y];
    235     if x>y then swap(x,y);
    236     change(1,x,y,z);
    237 end;
    238  
    239 procedure query(x,y:longint);
    240 var
    241     ans                                 :longint;
    242     a, b                                :longint;
    243 begin
    244     ans:=0;
    245     if dep[x]>dep[y] then swap(x,y);
    246     while dep[x]<dep[y] do
    247     begin
    248         ans:=ans+ask(1,num[top[y]],num[y]).sum;
    249         a:=ask(1,num[top[y]],num[top[y]]).succ;
    250         b:=ask(1,num[father[top[y]]],num[father[top[y]]]).pred;
    251         if a=b then dec(ans);
    252         y:=father[top[y]];
    253     end;
    254     while top[x]<>top[y] do
    255     begin
    256         ans:=ans+ask(1,num[top[y]],num[y]).sum;
    257         a:=ask(1,num[top[y]],num[top[y]]).succ;
    258         b:=ask(1,num[father[top[y]]],num[father[top[y]]]).pred;
    259         if a=b then dec(ans);
    260         ans:=ans+ask(1,num[top[x]],num[x]).sum;
    261         a:=ask(1,num[top[x]],num[top[x]]).succ;
    262         b:=ask(1,num[father[top[x]]],num[father[top[x]]]).pred;
    263         if a=b then dec(ans);
    264         x:=father[top[x]];
    265         y:=father[top[y]];
    266     end;
    267     x:=num[x];
    268     y:=num[y];
    269     if x>y then swap(x,y);
    270     ans:=ans+ask(1,x,y).sum;
    271     writeln(ans);
    272 end;
    273  
    274 procedure main;
    275 var
    276     i                                   :longint;
    277     c                                   :char;
    278     x, y, z                             :longint;
    279      
    280 begin
    281     readln;
    282     for i:=1 to m do
    283     begin
    284         read(c);
    285         if c='Q' then
    286         begin
    287             readln(x,y);
    288             query(x,y) 
    289         end else
    290         begin
    291             readln(x,y,z);
    292             paint(x,y,z);
    293         end;
    294     end;
    295 end;
    296  
    297 begin
    298     init;
    299     main;
    300 end.
  • 相关阅读:
    python算法:嵌套数组转变成一维数组
    python算法:约瑟夫问题
    python的加密算法(1):反转加密
    算法:桶排序
    正则表达式学习(3):相关符号解释
    代码这样写更优雅(1)
    正则表达式学习(2)
    神奇的Bank系统之旅哦
    C#之第五单元的项目打印购物单
    C#语言的基础
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3433551.html
Copyright © 2020-2023  润新知