zoukankan      html  css  js  c++  java
  • 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.
  • 相关阅读:
    【2018.05.05 C与C++基础】C++中的自动废料收集:概念与问题引入
    【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题
    【2018.04.19 ROS机器人操作系统】机器人控制:运动规划、路径规划及轨迹规划简介之一
    March 11th, 2018 Week 11th Sunday
    March 10th, 2018 Week 10th Saturday
    March 09th, 2018 Week 10th Friday
    March 08th, 2018 Week 10th Thursday
    March 07th, 2018 Week 10th Wednesday
    ubantu之Git使用
    AMS分析 -- 启动过程
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3433551.html
Copyright © 2011-2022 走看看