zoukankan      html  css  js  c++  java
  • 【BZOJ3123】森林(主席树,启发式合并)

    题意:一个带点权的森林,要求维护以下操作:

    1.询问路径上的点权K大值

    2.两点之间连边

    n,m<=80000

    思路:如果树的结构不发生变化只需要维护DFS序

    现在因为树的结构发生变化,要将两棵树合并,这步可以用启发式合并,将比较小的树暴力连接到较大的树上面

    离线的LCA算法无法维护,而倍增可以合并,所以用倍增求LCA

    其余就是主席树,维护根到点的权值线段树就行了

    机房里的罗爷爷写法比我高到不知道哪里去了

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int M=200010;
     6 int cas,n,m,q,i,x,y,k,edgenum,cnt,ans;
     7 int a[M],b[M],c[M],head[M],vet[M],next[M],dep[M],fa[M][20],f[M],size[M],root[M];
     8 struct node{int l,r,w;}tree[M*100];
     9 bool cmp(int x,int y){return a[x]<a[y];}
    10 int search(int x){
    11     if (f[x]!=x)f[x]=search(f[x]);
    12     return f[x];
    13 }
    14 void addedge(int x,int y){
    15     vet[++edgenum]=y;
    16     next[edgenum]=head[x];
    17     head[x]=edgenum;
    18 }
    19 void update(int x,int l,int r,int &p){
    20     tree[++cnt]=tree[p];p=cnt;tree[p].w++;
    21     if (l==r)return;
    22     int mid=l+r>>1;
    23     if (x<=mid)update(x,l,mid,tree[p].l);
    24         else update(x,mid+1,r,tree[p].r);
    25 }
    26 int query(int l,int r,int k,int x,int y,int z,int w){
    27     if (l==r)return l;
    28     int mid=l+r>>1,t=tree[tree[x].l].w+tree[tree[y].l].w-tree[tree[z].l].w-tree[tree[w].l].w;
    29     if (t>=k)return query(l,mid,k,tree[x].l,tree[y].l,tree[z].l,tree[w].l);
    30         else return query(mid+1,r,k-t,tree[x].r,tree[y].r,tree[z].r,tree[w].r);
    31 }
    32 int lca(int x,int y){
    33     if (dep[x]<dep[y])swap(x,y);
    34     int t=dep[x]-dep[y];
    35     for (int i=0;i<=16;i++)
    36         if (t&(1<<i))x=fa[x][i];
    37     for (int i=16;i>=0;i--)
    38         if (fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    39     if (x==y)return x;
    40     return fa[x][0];
    41 }
    42 void dfs(int u,int pre){
    43     fa[u][0]=pre;
    44     for (int i=1;i<=16;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
    45     root[u]=root[pre];
    46     update(c[u],1,n,root[u]);
    47     for (int e=head[u];e;e=next[e]){
    48         int v=vet[e];
    49         if (v==pre)continue;
    50         dep[v]=dep[u]+1;
    51         dfs(v,u);
    52     }
    53 }
    54 void link(int x,int y){
    55     int p=search(x),q=search(y);
    56     if (size[p]>size[q]){swap(x,y);swap(p,q);}
    57     dep[x]=dep[y]+1;
    58     dfs(x,y);
    59     f[p]=q;size[q]+=size[p];
    60     addedge(x,y);
    61     addedge(y,x);
    62 }
    63 int main(){
    64     scanf("%d",&cas);
    65     scanf("%d%d%d",&n,&m,&q);
    66     for (i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=i;
    67     sort(b+1,b+n+1,cmp);
    68     for (i=1;i<=n;i++)c[b[i]]=i;
    69     for (i=1;i<=n;i++)f[i]=i,size[i]=1;
    70     cnt=n;
    71     for (i=1;i<=n;i++)root[i]=i,update(c[i],1,n,root[i]);
    72     for (i=1;i<=m;i++){
    73         scanf("%d%d",&x,&y);
    74         link(x,y);
    75     }
    76     while (q--){
    77         char s[10];
    78         scanf("%s",s);
    79         if (s[0]=='L'){
    80             scanf("%d%d",&x,&y);
    81             x^=ans;y^=ans;
    82             link(x,y);
    83         }else{
    84             scanf("%d%d%d",&x,&y,&k);
    85             x^=ans;y^=ans;k^=ans;
    86             int z=lca(x,y);
    87             printf("%d
    ",ans=a[b[query(1,n,k,root[x],root[y],root[z],root[fa[z][0]])]]);
    88         }
    89     }
    90 }

    这是我的萎靡写法

      1 var t:array[0..22000000]of record
      2                            l,r,s:longint;
      3                           end;
      4     f:array[0..300000,0..20]of longint;
      5     root,head,c,a,hash,h,dep,stk,size:array[0..500000]of longint;
      6     vet,next:array[0..610000]of longint;
      7     n,m,x,y,z,lastans,i,j,tot,cnt,k,s,up,top,que:longint;
      8     ch:string;
      9 
     10 procedure swap(var x,y:longint);
     11 var t:longint;
     12 begin
     13  t:=x; x:=y; y:=t;
     14 end;
     15 
     16 procedure qsort(l,r:longint);
     17 var i,j,mid:longint;
     18 begin
     19  i:=l; j:=r; mid:=c[(l+r)>>1];
     20  repeat
     21   while mid>c[i] do inc(i);
     22   while mid<c[j] do dec(j);
     23   if i<=j then
     24   begin
     25    swap(c[i],c[j]);
     26    inc(i); dec(j);
     27   end;
     28  until i>j;
     29  if l<j then qsort(l,j);
     30  if i<r then qsort(i,r);
     31 end;
     32 
     33 function lsh(x:longint):longint;
     34 var l,r,mid:longint;
     35 begin
     36  l:=1; r:=up;
     37  while l<=r do
     38  begin
     39   mid:=(l+r)>>1;
     40   if x=hash[mid] then exit(mid);
     41   if x<hash[mid] then r:=mid-1
     42    else l:=mid+1;
     43  end;
     44 end;
     45 
     46 function find(k:longint):longint;
     47 begin
     48  if h[k]<>k then h[k]:=find(h[k]);
     49  exit(h[k]);
     50 end;
     51 
     52 procedure add(a,b:longint);
     53 begin
     54  inc(tot);
     55  next[tot]:=head[a];
     56  vet[tot]:=b;
     57  head[a]:=tot;
     58 end;
     59 
     60 procedure pushup(p:longint);
     61 begin
     62  t[p].s:=t[t[p].l].s+t[t[p].r].s;
     63 end;
     64 
     65 procedure update(l,r,x:longint;var y:longint;v:longint);
     66 var mid:longint;
     67 begin
     68  inc(cnt); y:=cnt;
     69  t[y]:=t[x]; inc(t[y].s);
     70  if l=r then exit;
     71  mid:=(l+r)>>1;
     72  if v<=mid then update(l,mid,t[x].l,t[y].l,v)
     73   else update(mid+1,r,t[x].r,t[y].r,v);
     74  pushup(y);
     75 end;
     76 
     77 procedure dfs(u,pre:longint);
     78 var e,v,x,y:longint;
     79 begin
     80  update(1,up,root[pre],root[u],a[u]);
     81  e:=head[u];
     82  dep[u]:=dep[pre]+1;
     83  f[u,0]:=pre;
     84  while e<>0 do
     85  begin
     86   v:=vet[e];
     87   if v<>pre then
     88   begin
     89    dfs(v,u);
     90    x:=find(v); y:=find(u);
     91    if size[x]<size[y] then
     92    begin
     93     size[x]:=size[y]+size[x];
     94     h[y]:=x;
     95    end
     96     else begin size[y]:=size[x]+size[y]; h[x]:=y; end;
     97   end;
     98   e:=next[e];
     99  end;
    100 end;
    101 
    102 function lca(x,y:longint):longint;
    103 var i,d:longint;
    104 begin
    105  if dep[x]<dep[y] then swap(x,y);
    106  d:=dep[x]-dep[y];
    107  for i:=0 to 20 do
    108   if d and (1<<i)>0 then x:=f[x,i];
    109  for i:=20 downto 0 do
    110   if f[x,i]<>f[y,i] then
    111   begin
    112    x:=f[x,i]; y:=f[y,i];
    113   end;
    114  if x=y then exit(x);
    115  exit(f[x,0]);
    116 end;
    117 
    118 function query(l,r,x,y,z,w,k:longint):longint;
    119 var mid,tmp:longint;
    120 begin
    121  if l=r then exit(l);
    122  mid:=(l+r)>>1;
    123  tmp:=t[t[x].l].s+t[t[y].l].s-t[t[z].l].s-t[t[w].l].s;
    124  if tmp>=k then
    125  begin
    126   x:=t[x].l; y:=t[y].l; z:=t[z].l; w:=t[w].l;
    127   exit(query(l,mid,x,y,z,w,k));
    128  end
    129   else
    130   begin
    131    x:=t[x].r; y:=t[y].r; z:=t[z].r; w:=t[w].r;
    132    exit(query(mid+1,r,x,y,z,w,k-tmp));
    133   end;
    134 end;
    135 
    136 function ask(x,y,z:longint):longint;
    137 var q:longint;
    138 begin
    139  q:=lca(x,y);
    140  exit(hash[query(1,up,root[x],root[y],root[q],root[f[q,0]],z)]);
    141 end;
    142 
    143 procedure rebuild(u,pre:longint);
    144 var e,v:longint;
    145 begin
    146  inc(top); stk[top]:=u;
    147  update(1,up,root[pre],root[u],a[u]);
    148  dep[u]:=dep[pre]+1;
    149  f[u,0]:=pre;
    150  e:=head[u];
    151  while e<>0 do
    152  begin
    153   v:=vet[e];
    154   if v<>pre then rebuild(v,u);
    155   e:=next[e];
    156  end;
    157 end;
    158 
    159 procedure merge(x,y:longint);
    160 var tx,ty,z,i,j:longint;
    161 begin
    162  tx:=find(x); ty:=find(y);
    163  if size[tx]>size[ty] then
    164  begin
    165   swap(tx,ty); swap(x,y);
    166  end;
    167  top:=0;
    168  add(x,y); add(y,x);
    169  rebuild(x,y);
    170  h[tx]:=ty; size[ty]:=size[ty]+size[tx];
    171  for i:=1 to 20 do
    172   for j:=1 to top do
    173   begin
    174    z:=stk[j];
    175    f[z,i]:=f[f[z,i-1],i-1];
    176   end;
    177 end;
    178 
    179 begin
    180  assign(input,'bzoj3123.in'); reset(input);
    181  assign(output,'bzoj3123.out'); rewrite(output);
    182  readln(x);
    183  readln(n,m,que);
    184  for i:=1 to n do
    185  begin
    186   read(a[i]);
    187   c[i]:=a[i];
    188  end;
    189  qsort(1,n);
    190  up:=1; hash[1]:=c[1];
    191  for i:=2 to n do
    192   if c[i]<>c[i-1] then begin inc(up); hash[up]:=c[i]; end;
    193  for i:=1 to n do a[i]:=lsh(a[i]);
    194  for i:=1 to m do
    195  begin
    196   readln(x,y);
    197   add(x,y);
    198   add(y,x);
    199  end;
    200  for i:=1 to n do
    201  begin
    202   h[i]:=i; size[i]:=1;
    203  end;
    204  for i:=1 to n do
    205   if root[i]=0 then dfs(i,0);
    206  for i:=1 to 20 do
    207   for j:=1 to n do f[j,i]:=f[f[j,i-1],i-1];
    208  for i:=1 to que do
    209  begin
    210   readln(ch); s:=0; k:=length(ch); x:=0; y:=0; z:=0;
    211   for j:=2 to k do
    212   begin
    213    if ch[j]=' ' then begin if ch[j-1]<>' ' then inc(s); continue; end;
    214    if s=1 then x:=x*10+ord(ch[j])-ord('0');
    215    if s=2 then y:=y*10+ord(ch[j])-ord('0');
    216    if s=3 then z:=z*10+ord(ch[j])-ord('0');
    217   end;
    218   if ch[1]='Q' then
    219   begin
    220    x:=x xor lastans; y:=y xor lastans; z:=z xor lastans; //writeln(x,' ',y,' ',z);
    221    k:=ask(x,y,z);
    222    writeln(k);
    223    lastans:=k;
    224   end
    225    else
    226    begin
    227     x:=x xor lastans; y:=y xor lastans;// writeln(x,' ',y,' ',z);
    228     merge(x,y);
    229    end;
    230 
    231  end;
    232  close(input);
    233  close(output);
    234 end.
  • 相关阅读:
    线性时间将两个有序链表合成一个有序链表(constant additional space)
    C++定义指针数组
    cmd运行java编译文件
    java的方法
    Java流程控制
    用户交互-Scanner
    Java的注释
    编译型语言和解释性语言
    JDK、JRE和JVM
    MarkDown的简单使用
  • 原文地址:https://www.cnblogs.com/myx12345/p/6242940.html
Copyright © 2011-2022 走看看