• 学军NOI训练13 T3 白黑树


    唉,大学军有自己的OJ就是好,无限orz

    只有周六的比赛是开放的囧,这场比赛最后因为虚拟机卡住没有及时提交……

    否则就能让大家看到我有多弱了……

    前两题题解写的很详细,可以自己去看,我来随便扯扯T3好了

    题目是这样的:

    有一棵以1为根的白黑树,每个节点都是黑色或白色,初始权值是0。维护两个操作:

    1.选定一个点a,对于所有黑色的点i,将lca(a,i)的权值加上i; 2.将a号点的颜色反转。

    最后求每个点权值

    很容易想出这样一个暴力:先考虑1操作,权值增加的点一定是a到根路径上的点

    且每个点增加的权值都是自己子树内黑点编号和-路径下一个点的子树内黑点遍和(a增加的就是自己子树内黑点的编号和)

    这样不难想到一个用dfs序的O(dlogn)+O(logn)(分别代表两个操作复杂度的做法,d是树的深度)

    这样可以跑过深度很小的数据(比如菊花图)

    但算法还有很大的优化空间,因为路径上点的操作其实是非常类似的

    考虑树链剖分的做法,树链剖分后的复杂度保证是基于这个定理: 任意一点到根的路径所经过的轻边不超过logn

    因此,对于操作1经过轻边到达的点以及点a,我们还像之前的做法(子树和-子树和)计算贡献,这样就是O(log^2)

    下面考虑重链上的点怎么快速统计,设一段重链为u...p,q...v

    当前我们走了一条轻边到了q,进入了一条重链上,则我们要快速处理u...p这一段

    任何一个非叶子节点i都在一条重链上,定义重链下一个点叫作重儿子,除此之外点i还延伸出一些轻边,那些轻边延伸到的点我们叫做轻儿子

    考虑操作1,在重链上的一点x,如果他的重儿子y及其子树上的黑点会对x产生影响

    则操作1的点a一定落在x的轻儿子的子树中,而我们知道,从a这样往上爬,

    x一定是通过一条轻边到达的点,根据之前的约定,我们是通过子树直接计算对x的影响的

    如果a就是x,那也是通过子树直接计算对x的权值影响的

    因此在考虑一段重链u...p上的点x,我们是不用他重儿子的子树对他权值的影响,只要考虑,x的轻儿子子树中的黑点和自身是否是黑点的影响即可:

    设w[x]为x轻儿子子树以及自身黑点的编号和,在操作1中,我们只要对一段重链u...p打上+1 tag即可;

    相当于每个点x的权值加上了w[x]*tag[x],通过线段树,这样的复杂度也是O(log^2);

    如果出现操作2怎么办呢,经过之前的分析就很简单了,我们先维护dfs序的子树和

    然后只要顺着a向根走,更新a点以及经过轻边到达的点x(更新w[],计算之前tag带来的影响)就可以了

      1 type node=record
      2        po,next:longint;
      3      end;
      4 
      5 var e:array[0..400010] of node;
      6     top,p,s,fa,d,a,b,c:array[0..200010] of longint;
      7     f,w,ans:array[0..200010] of int64;
      8     tree:array[0..200010*4] of longint;
      9     t,i,n,m,len,x,y:longint;
     10 
     11 function lowbit(x:longint):longint;
     12   begin
     13     exit(x and (-x));
     14   end;
     15 
     16 procedure add(x,y:longint);
     17   begin
     18     inc(len);
     19     e[len].po:=y;
     20     e[len].next:=p[x];
     21     p[x]:=len;
     22   end;
     23 
     24 procedure ins(x,w:longint);
     25   begin
     26     while x<=n do
     27     begin
     28       f[x]:=f[x]+w;
     29       x:=x+lowbit(x);
     30     end;
     31   end;
     32 
     33 
     34 procedure dfs1(x:longint);
     35   var i,y:longint;
     36   begin
     37     s[x]:=1;
     38     i:=p[x];
     39     while i<>0 do
     40     begin
     41       y:=e[i].po;
     42       if s[y]=0 then
     43       begin
     44         fa[y]:=x;
     45         d[y]:=d[x]+1;
     46         dfs1(y);
     47         s[x]:=s[x]+s[y];
     48       end;
     49       i:=e[i].next;
     50     end;
     51   end;
     52 
     53 procedure dfs2(x:longint);
     54   var i,y,q:longint;
     55   begin
     56     inc(t);
     57     b[x]:=t;
     58     a[t]:=x;
     59     q:=0;
     60     i:=p[x];
     61     while i<>0 do
     62     begin
     63       y:=e[i].po;
     64       if b[y]=0 then
     65         if s[y]>s[q] then q:=y;
     66       i:=e[i].next;
     67     end;
     68     if q<>0 then
     69     begin
     70       top[q]:=top[x];
     71       dfs2(q);
     72     end;
     73     i:=p[x];
     74     while i<>0 do
     75     begin
     76       y:=e[i].po;
     77       if b[y]=0 then
     78       begin
     79         top[y]:=y;
     80         dfs2(y);
     81       end;
     82       i:=e[i].next;
     83     end;
     84   end;
     85 
     86 function ask(x:longint):int64;
     87   begin
     88     ask:=0;
     89     while x>0 do
     90     begin
     91       ask:=ask+f[x];
     92       x:=x-lowbit(x);
     93     end;
     94   end;
     95 
     96 procedure push(i:longint);
     97   begin
     98     if tree[i]<>0 then
     99     begin
    100       inc(tree[i*2],tree[i]);
    101       inc(tree[i*2+1],tree[i]);
    102       tree[i]:=0;
    103     end;
    104   end;
    105 
    106 procedure get(i,l,r,x:longint);
    107   var m:longint;
    108   begin
    109     if l=r then
    110     begin
    111       inc(ans[a[l]],w[a[l]]*int64(tree[i]));
    112       tree[i]:=0;
    113     end
    114     else begin
    115       m:=(l+r) shr 1;
    116       push(i);
    117       if x<=m then get(i*2,l,m,x)
    118       else get(i*2+1,m+1,r,x);
    119     end;
    120   end;
    121 
    122 procedure tag(i,l,r,x,y:longint);
    123   var m:longint;
    124   begin
    125     if (x<=l) and (y>=r) then
    126       inc(tree[i])
    127     else begin
    128       m:=(l+r) shr 1;
    129       push(i);
    130       if x<=m then tag(i*2,l,m,x,y);
    131       if y>m then tag(i*2+1,m+1,r,x,y);
    132     end;
    133   end;
    134 
    135 procedure work(x,z:longint);
    136   begin
    137     ins(b[x],z);
    138     while x<>0 do
    139     begin
    140       get(1,1,n,b[x]);
    141       w[x]:=w[x]+z;
    142       x:=fa[top[x]];
    143     end;
    144   end;
    145 
    146 procedure calc(x:longint);
    147   var y:longint;
    148   begin
    149     y:=0;
    150     while x<>0 do
    151     begin
    152       inc(ans[x],ask(b[x]+s[x]-1)-ask(b[x]-1));
    153       if y<>0 then
    154         dec(ans[x],ask(b[y]+s[y]-1)-ask(b[y]-1));
    155       if x<>top[x] then tag(1,1,n,b[top[x]],b[x]-1);
    156       y:=top[x];
    157       x:=fa[y];
    158     end;
    159   end;
    160 
    161 begin
    162   readln(n,m);
    163   for i:=1 to n do
    164     read(c[i]);
    165   for i:=1 to n-1 do
    166   begin
    167     readln(x,y);
    168     add(x,y);
    169     add(y,x);
    170   end;
    171   dfs1(1);
    172   top[1]:=1;
    173   dfs2(1);
    174   for i:=1 to n do
    175     if c[i]=1 then work(i,i);
    176   for i:=1 to m do
    177   begin
    178     readln(x,y);
    179     if x=1 then calc(y)
    180     else begin
    181       if c[y]=1 then work(y,-y)
    182       else work(y,y);
    183       c[y]:=1-c[y];
    184     end;
    185   end;
    186   for i:=1 to n do
    187   begin
    188     get(1,1,n,b[i]);
    189     writeln(ans[i]);
    190   end;
    191 end.
    View Code

     

  • 相关阅读:
    Comet OJ
    Comet OJ
    Comet OJ
    Comet OJ
    Codeforces Round #562 (Div. 2)
    P1202 USACO1.1 黑色星期五
    P1201 USACO1.1 贪婪的送礼者
    【线段树】HDU1166:敌兵布阵
    标准C++中的string类的用法总结(转)
    【递归】分形
  • 原文地址:https://www.cnblogs.com/phile/p/4593450.html
Copyright © 2020-2023  润新知