• bzoj2588


    一开始一看树上的操作,就无脑写了树链剖分+主席树

    然后果断T了,因为树链剖分+主席树必然带来两个log的复杂度

    而且树链剖分复杂度还比较大……

    后来发现其实没必要,在这道题,我们可以直接利用主席树维护

    只不过,每个点维护的是它到它的祖先上数值出现的个数

    则u,v之间各个数值出现的数值=tree[u]+tree[v]-tree[lca(u,v)]-tree[fa[lca(u,v)]];

    这是一个满足区间减法的问题所以可以这么做

    总结一下,在静态树上(相对于动态树而言,没有改变树的形态)

    1. 如果问题满足区间减法性质,如求k大,那就直接做,或者用dfs序(下篇再写)

    2. 如果不满足,那就要套树链剖分了

      1 const maxn=100010;
      2 type node=record
      3        po,next:longint;
      4      end;
      5      point=record
      6        l,r,s:longint;
      7      end;
      8 
      9 var tree:array[0..maxn*20] of point;
     10     w:array[0..2*maxn] of node;
     11     h,p,c,b,a,q1,q2,rank,sa,fa,d:array[0..maxn] of longint;
     12     anc:array[0..maxn,0..20] of longint;
     13     j,t,z,e,i,n,m,k,x,y,len,ans,s:longint;
     14 
     15 procedure swap(var a,b:longint);
     16   var c:longint;
     17   begin
     18     c:=a;
     19     a:=b;
     20     b:=c;
     21   end;
     22 
     23 procedure update(i:longint);
     24   begin
     25     tree[i].s:=tree[tree[i].l].s+tree[tree[i].r].s;
     26   end;
     27 
     28 procedure add(x,y:longint);
     29   begin
     30     inc(len);
     31     w[len].po:=y;
     32     w[len].next:=p[x];
     33     p[x]:=len;
     34   end;
     35 
     36 procedure sort(l,r: longint);
     37   var i,j,x:longint;
     38   begin
     39     i:=l;
     40     j:=r;
     41     x:=a[(l+r) div 2];
     42     repeat
     43       while (a[i]<x) do inc(i);
     44       while (x<a[j]) do dec(j);
     45       if not(i>j) then
     46       begin
     47         swap(a[i],a[j]);
     48         swap(c[i],c[j]);
     49         inc(i);
     50         j:=j-1;
     51       end;
     52     until i>j;
     53     if l<j then sort(l,j);
     54     if i<r then sort(i,r);
     55   end;
     56 
     57 function build(l,r:longint):longint;
     58   var q,m:longint;
     59   begin
     60     inc(t);
     61     if l=r then exit(t)
     62     else begin
     63       q:=t;
     64       m:=(l+r) shr 1;
     65       tree[q].l:=build(l,m);
     66       tree[q].r:=build(m+1,r);
     67       exit(q);
     68     end;
     69   end;
     70 
     71 function add(last,l,r,x:longint):longint;
     72   var q,m:longint;
     73   begin
     74     inc(t);
     75     if l=r then
     76     begin
     77       tree[t].s:=tree[last].s+1;
     78       exit(t);
     79     end
     80     else begin
     81       q:=t;
     82       m:=(l+r) shr 1;
     83       if x<=m then
     84       begin
     85         tree[q].r:=tree[last].r;
     86         last:=tree[last].l;
     87         tree[q].l:=add(last,l,m,x);
     88       end
     89       else begin
     90         tree[q].l:=tree[last].l;
     91         last:=tree[last].r;
     92         tree[q].r:=add(last,m+1,r,x);
     93       end;
     94       update(q);
     95       exit(q);
     96     end;
     97   end;
     98 
     99 function getans(l,r,k:longint):longint;
    100   var i,m,s1:longint;
    101   begin
    102     if l=r then
    103       exit(sa[l])
    104     else begin
    105       m:=(l+r) shr 1;
    106       s1:=tree[tree[x].l].s+tree[tree[y].l].s-tree[tree[z].l].s-tree[tree[e].l].s;
    107       if s1>=k then
    108       begin
    109         x:=tree[x].l;
    110         y:=tree[y].l;
    111         z:=tree[z].l;
    112         e:=tree[e].l;
    113         exit(getans(l,m,k));
    114       end
    115       else begin
    116         x:=tree[x].r;
    117         y:=tree[y].r;
    118         z:=tree[z].r;
    119         e:=tree[e].r;
    120         k:=k-s1;
    121         exit(getans(m+1,r,k));
    122       end;
    123     end;
    124   end;
    125 
    126 function lca(x,y:longint):longint;
    127   var i,p:longint;
    128   begin
    129     if d[x]<d[y] then swap(x,y);
    130     if x=y then exit(x);
    131     p:=trunc(ln(d[x])/ln(2));
    132     for i:=p downto 0 do
    133       if d[x]-1 shl i>=d[y] then x:=anc[x,i];
    134     if x=y then exit(x);
    135     for i:=p downto 0 do
    136       if (anc[x,i]<>anc[y,i]) and (anc[x,i]<>0) then
    137       begin
    138         x:=anc[x,i];
    139         y:=anc[y,i];
    140       end;
    141     exit(fa[x]);
    142   end;
    143 
    144 procedure dfs(x:longint);
    145   var i,y:longint;
    146   begin
    147     h[x]:=add(h[fa[x]],1,s,rank[x]);
    148     i:=p[x];
    149     while i<>0 do
    150     begin
    151       y:=w[i].po;
    152       if fa[x]<>y then
    153       begin
    154         d[y]:=d[x]+1;
    155         fa[y]:=x;
    156         dfs(y);
    157       end;
    158       i:=w[i].next;
    159     end;
    160   end;
    161 
    162 begin
    163   readln(n,m);
    164   for i:=1 to n do
    165   begin
    166     read(a[i]);
    167     c[i]:=i;
    168   end;
    169   sort(1,n);
    170   s:=1;
    171   sa[1]:=a[1];
    172   rank[c[1]]:=1;
    173   for i:=2 to n do
    174   begin
    175     if a[i]<>a[i-1] then
    176     begin
    177       inc(s);
    178       sa[s]:=a[i];
    179     end;
    180     rank[c[i]]:=s;
    181   end;
    182   for i:=1 to n-1 do
    183   begin
    184     readln(x,y);
    185     add(x,y);
    186     add(y,x);
    187   end;
    188   h[0]:=build(1,s);
    189   dfs(1);
    190 
    191   for i:=1 to n do
    192     anc[i,0]:=fa[i];
    193   k:=trunc(ln(n)/ln(2));
    194   for j:=1 to k do
    195     for i:=1 to n do
    196     begin
    197       x:=anc[i,j-1];
    198       if x<>0 then anc[i,j]:=anc[x,j-1];
    199     end;
    200 
    201   ans:=0;
    202   for i:=1 to m do
    203   begin
    204     readln(x,y,k);
    205     x:=x xor ans;
    206     z:=lca(x,y);
    207     e:=h[fa[z]];
    208     z:=h[z];
    209     x:=h[x];
    210     y:=h[y];
    211     ans:=getans(1,s,k);
    212     write(ans);
    213     if i<>m then writeln;
    214   end;
    215 end.
    View Code
  • 相关阅读:
    MySQL 替换和截取指定位置字符串
    notepad++安装XML格式化插件
    个人信用报告,长啥样?怎么查?
    MySQL 查询decimal字段去除自动补零
    mapstruct使用详解
    电商物流行业中的RDC、FDC和TDC分别表示什么意思?发网详解
    借助Proxifier实现内网访问
    C++源码流程图分析!
    FFmpeg中AVPacket处理函数av_free_packet()和av_packet_free()的区别以及用法
    fopen 和它的读写标识 r、r+、rb+、rt+、w+.....
  • 原文地址:https://www.cnblogs.com/phile/p/4473092.html
Copyright © 2020-2023  润新知