• 【BZOJ3611】大工程(虚树,DFS序,树形DP)


    题意:有一棵树,树有边权,有若干次询问,给出一些点,求:

    1.这些点互相之间的距离之和

    2.点对距离中的最大和最小值

    n<=1000000 

    q<=50000并且保证所有k之和<=2*n 
     
    思路:感谢Gold_7
    建立虚树,在上面树形DP即可
    最大值和最小值用了一种精妙的写法来保证是最值+次值
    终于会写类似点对距离和的树形DP了
      1 var head,vet,next,len,
      2     head1,vet1,next1,len1,
      3     h,stk,b,dep,dfn,flag,c:array[0..2100000]of longint;
      4     dp:array[1..1000000,1..2]of longint;
      5     size,g:array[1..1000000]of int64;
      6     f:array[1..1000000,0..21]of longint;
      7     n,i,tot,que,ans1,ans2,time,x,y:longint;
      8     ans:int64;
      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 function min(x,y:int64):int64;
     17 begin
     18  if x<y then exit(x);
     19  exit(y);
     20 end;
     21 
     22 function max(x,y:int64):int64;
     23 begin
     24  if x>y then exit(x);
     25  exit(y);
     26 end;
     27 
     28 procedure add(a,b,c:longint);
     29 begin
     30  inc(tot);
     31  next[tot]:=head[a];
     32  vet[tot]:=b;
     33  len[tot]:=c;
     34  head[a]:=tot;
     35 end;
     36 
     37 procedure qsort(l,r:longint);
     38 var i,j,mid:longint;
     39 begin
     40  i:=l; j:=r; mid:=b[(l+r)>>1];
     41  repeat
     42   while mid>b[i] do inc(i);
     43   while mid<b[j] do dec(j);
     44   if i<=j then
     45   begin
     46    swap(h[i],h[j]);
     47    swap(b[i],b[j]);
     48    inc(i); dec(j);
     49   end;
     50  until i>j;
     51  if l<j then qsort(l,j);
     52  if i<r then qsort(i,r);
     53 end;
     54 
     55 function lca(x,y:longint):longint;
     56 var i,d:longint;
     57 begin
     58  if dep[x]<dep[y] then swap(x,y);
     59  d:=dep[x]-dep[y];
     60  for i:=0 to 21 do
     61   if d and (1<<i)>0 then x:=f[x,i];
     62  for i:=21 downto 0 do
     63   if f[x,i]<>f[y,i] then
     64   begin
     65    x:=f[x,i]; y:=f[y,i];
     66   end;
     67  if x=y then exit(x);
     68  exit(f[x,0]);
     69 end;
     70 
     71 procedure dfs(u:longint);
     72 var e,v,i:longint;
     73 begin
     74  for i:=1 to 21 do
     75  begin
     76   if dep[u]<(1<<i) then break;
     77   f[u,i]:=f[f[u,i-1],i-1];
     78  end;
     79  inc(time); dfn[u]:=time;
     80  flag[u]:=1;
     81  e:=head[u];
     82  while e<>0 do
     83  begin
     84   v:=vet[e];
     85   if flag[v]=0 then
     86   begin
     87    f[v,0]:=u;
     88    dep[v]:=dep[u]+1;
     89    dfs(v);
     90   end;
     91   e:=next[e];
     92  end;
     93 end;
     94 
     95 procedure add1(a,b:longint);
     96 begin
     97  if a=b then exit;
     98  inc(tot);
     99  next1[tot]:=head1[a];
    100  vet1[tot]:=b;
    101  len1[tot]:=abs(dep[a]-dep[b]);
    102  head1[a]:=tot;
    103 end;
    104 
    105 procedure dfs2(u:longint);
    106 var e,v:longint;
    107 begin
    108  size[u]:=c[u];
    109  g[u]:=0;
    110  if c[u]=1 then begin dp[u,1]:=0; dp[u,2]:=0; end
    111   else begin dp[u,1]:=-maxlongint div 3; dp[u,2]:=maxlongint div 3; end;
    112  e:=head1[u];
    113  while e<>0 do
    114  begin
    115   v:=vet1[e];
    116   dfs2(v);
    117   ans:=ans+size[v]*g[u]+size[u]*g[v]+size[u]*size[v]*len1[e];
    118   size[u]:=size[u]+size[v];
    119   g[u]:=g[u]+g[v]+size[v]*len1[e];
    120   ans1:=max(ans1,dp[u,1]+dp[v,1]+len1[e]);
    121   ans2:=min(ans2,dp[u,2]+dp[v,2]+len1[e]);
    122   dp[u,1]:=max(dp[u,1],dp[v,1]+len1[e]);
    123   dp[u,2]:=min(dp[u,2],dp[v,2]+len1[e]);
    124   e:=next1[e];
    125  end;
    126  head1[u]:=0;
    127 end;
    128 
    129 procedure solve;
    130 var q,top,i,now,m,p:longint;
    131 begin
    132  tot:=0;
    133  read(m);
    134  for i:=1 to m do
    135  begin
    136   read(h[i]); b[i]:=dfn[h[i]];
    137   c[h[i]]:=1;
    138  end;
    139  qsort(1,m);
    140  //q:=1;
    141  //for i:=2 to m do
    142   //if lca(h[i],h[q])<>h[q] then begin inc(q); h[q]:=h[i]; end;
    143  stk[1]:=1; top:=1;
    144  for i:=1 to m do
    145  begin
    146   now:=h[i]; p:=lca(now,stk[top]);
    147   while true do
    148   begin
    149    if dep[p]>=dep[stk[top-1]] then
    150    begin
    151     add1(p,stk[top]); dec(top);
    152     if stk[top]<>p then begin inc(top); stk[top]:=p; end;
    153     break;
    154    end;
    155    add1(stk[top-1],stk[top]); dec(top);
    156   end;
    157   if stk[top]<>now then begin inc(top); stk[top]:=now; end;
    158  end;
    159  for i:=top-1 downto 1 do add1(stk[i],stk[i+1]);
    160  ans:=0; ans1:=-maxlongint div 3; ans2:=maxlongint div 3;
    161  dfs2(1);
    162  writeln(ans,' ',ans2,' ',ans1);
    163  for i:=1 to m do c[h[i]]:=0;
    164 end;
    165 
    166 
    167 begin
    168 
    169  readln(n);
    170  for i:=1 to n-1 do
    171  begin
    172   readln(x,y);
    173   add(x,y,1);
    174   add(y,x,1);
    175  end;
    176  dfs(1);
    177  readln(que);
    178  for i:=1 to que do solve;
    179  
    180 end.
    %了XYZ(虚树发明者)论文后的新的建虚树方法,简明易懂:
    1:加入所有原关键点并按DFS序排序
    2:将排序后两两相邻点对的LCA加入后去重,并再次排序
    3:将第二次排序后的点依次入栈,若栈顶元素y非插入元素x的祖先则退栈,直到栈顶元素为x的祖先为止,链接x,y
      1 var head,vet,next,len,
      2     head1,vet1,next1,len1,
      3     h,stk,b,dep,dfn,flag,c,d:array[0..2100000]of longint;
      4     dp:array[1..1000000,1..2]of longint;
      5     size,g:array[1..1000000]of int64;
      6     f:array[1..1000000,0..21]of longint;
      7     n,i,tot,que,ans1,ans2,time,x,y:longint;
      8     ans:int64;
      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 function min(x,y:int64):int64;
     17 begin
     18  if x<y then exit(x);
     19  exit(y);
     20 end;
     21 
     22 function max(x,y:int64):int64;
     23 begin
     24  if x>y then exit(x);
     25  exit(y);
     26 end;
     27 
     28 procedure add(a,b,c:longint);
     29 begin
     30  inc(tot);
     31  next[tot]:=head[a];
     32  vet[tot]:=b;
     33  len[tot]:=c;
     34  head[a]:=tot;
     35 end;
     36 
     37 procedure qsort1(l,r:longint);
     38 var i,j,mid:longint;
     39 begin
     40  i:=l; j:=r; mid:=b[(l+r)>>1];
     41  repeat
     42   while mid>b[i] do inc(i);
     43   while mid<b[j] do dec(j);
     44   if i<=j then
     45   begin
     46    swap(h[i],h[j]);
     47    swap(b[i],b[j]);
     48    inc(i); dec(j);
     49   end;
     50  until i>j;
     51  if l<j then qsort1(l,j);
     52  if i<r then qsort1(i,r);
     53 end;
     54 
     55 procedure qsort2(l,r:longint);
     56 var i,j,mid:longint;
     57 begin
     58  i:=l; j:=r; mid:=b[(l+r)>>1];
     59  repeat
     60   while mid>b[i] do inc(i);
     61   while mid<b[j] do dec(j);
     62   if i<=j then
     63   begin
     64    swap(d[i],d[j]);
     65    swap(b[i],b[j]);
     66    inc(i); dec(j);
     67   end;
     68  until i>j;
     69  if l<j then qsort2(l,j);
     70  if i<r then qsort2(i,r);
     71 end;
     72 
     73 function lca(x,y:longint):longint;
     74 var i,d:longint;
     75 begin
     76  if dep[x]<dep[y] then swap(x,y);
     77  d:=dep[x]-dep[y];
     78  for i:=0 to 21 do
     79   if d and (1<<i)>0 then x:=f[x,i];
     80  for i:=21 downto 0 do
     81   if f[x,i]<>f[y,i] then
     82   begin
     83    x:=f[x,i]; y:=f[y,i];
     84   end;
     85  if x=y then exit(x);
     86  exit(f[x,0]);
     87 end;
     88 
     89 procedure dfs(u:longint);
     90 var e,v,i:longint;
     91 begin
     92  for i:=1 to 21 do
     93  begin
     94   if dep[u]<(1<<i) then break;
     95   f[u,i]:=f[f[u,i-1],i-1];
     96  end;
     97  inc(time); dfn[u]:=time;
     98  flag[u]:=1;
     99  e:=head[u];
    100  while e<>0 do
    101  begin
    102   v:=vet[e];
    103   if flag[v]=0 then
    104   begin
    105    f[v,0]:=u;
    106    dep[v]:=dep[u]+1;
    107    dfs(v);
    108   end;
    109   e:=next[e];
    110  end;
    111 end;
    112 
    113 procedure add1(a,b:longint);
    114 begin
    115  if a=b then exit;
    116  inc(tot);
    117  next1[tot]:=head1[a];
    118  vet1[tot]:=b;
    119  len1[tot]:=abs(dep[a]-dep[b]);
    120  head1[a]:=tot;
    121 end;
    122 
    123 procedure dfs2(u:longint);
    124 var e,v:longint;
    125 begin
    126  size[u]:=c[u];
    127  g[u]:=0;
    128  if c[u]=1 then begin dp[u,1]:=0; dp[u,2]:=0; end
    129   else begin dp[u,1]:=-maxlongint div 3; dp[u,2]:=maxlongint div 3; end;
    130  e:=head1[u];
    131  while e<>0 do
    132  begin
    133   v:=vet1[e];
    134   dfs2(v);
    135   ans:=ans+size[v]*g[u]+size[u]*g[v]+size[u]*size[v]*len1[e];
    136   size[u]:=size[u]+size[v];
    137   g[u]:=g[u]+g[v]+size[v]*len1[e];
    138   ans1:=max(ans1,dp[u,1]+dp[v,1]+len1[e]);
    139   ans2:=min(ans2,dp[u,2]+dp[v,2]+len1[e]);
    140   dp[u,1]:=max(dp[u,1],dp[v,1]+len1[e]);
    141   dp[u,2]:=min(dp[u,2],dp[v,2]+len1[e]);
    142   e:=next1[e];
    143  end;
    144  head1[u]:=0;
    145 end;
    146 
    147 procedure solve;
    148 var q,top,i,now,m,p:longint;
    149 begin
    150  tot:=0;
    151  read(m);
    152  for i:=1 to m do
    153  begin
    154   read(h[i]); b[i]:=dfn[h[i]];
    155   c[h[i]]:=1;
    156  end;
    157  qsort1(1,m);
    158  q:=0;
    159  for i:=1 to m do
    160  begin
    161   inc(q); d[q]:=h[i]; flag[h[i]]:=1;
    162  end;
    163  for i:=1 to m-1 do
    164  begin
    165   p:=lca(h[i],h[i+1]);
    166   if flag[p]=0 then begin flag[p]:=1; inc(q); d[q]:=p; end;
    167  end;
    168  for i:=1 to q do b[i]:=dfn[d[i]];
    169  qsort2(1,q);
    170 
    171  stk[1]:=d[1]; top:=1;
    172  for i:=2 to q do
    173  begin
    174   x:=d[i];
    175   while true do
    176   begin
    177    y:=stk[top];
    178    if lca(x,y)<>y then dec(top)
    179     else
    180     begin
    181      add1(y,x);
    182      break;
    183     end;
    184   end;
    185   inc(top); stk[top]:=x;
    186  end;
    187 
    188 
    189  ans:=0; ans1:=-maxlongint div 3; ans2:=maxlongint div 3;
    190  dfs2(d[1]);
    191  writeln(ans,' ',ans2,' ',ans1);
    192  for i:=1 to m do c[h[i]]:=0;
    193  for i:=1 to q do flag[d[i]]:=0;
    194 end;
    195 
    196 
    197 begin
    198  assign(input,'bzoj3611.in'); reset(input);
    199  assign(output,'bzoj3611.out'); rewrite(output);
    200  readln(n);
    201  for i:=1 to n-1 do
    202  begin
    203   readln(x,y);
    204   add(x,y,1);
    205   add(y,x,1);
    206  end;
    207  dfs(1);
    208  readln(que);
    209  fillchar(flag,sizeof(flag),0);
    210  for i:=1 to que do solve;
    211  close(input);
    212  close(output);
    213 end.
     
  • 相关阅读:
    C#学习笔记——读写ini文件
    C#学习笔记——控件
    C#学习笔记——SerialPort类
    halcon学习笔记——遍历文件夹与文件选择
    halcon学习笔记——图像的预处理
    C#中创建和使用动态链接库
    C#学习笔记——控件的命名规范
    halcon学习笔记——(1)HDevelop language(语法结构特点)
    C#学习笔记——基础概念回顾
    C#学习笔记——继承窗体
  • 原文地址:https://www.cnblogs.com/myx12345/p/6187633.html
Copyright © 2020-2023  润新知