【BZOJ4477】字符串树(可持久化Trie)

此题花费我整整三天的功夫。还在NoiP贴吧发过贴。

最后发现trie树建新节点时信息未完全复制,真是愚蠢之极。

言归正传。

如果我们已经知道了每个点上的trie树那么询问就是sum[x]+sum[y]-sum[lca(x,y)]*2

然后就是trie树变可持久化。

DFS2中插入所有字符串,建立新节点,复制出现次数与trie树的next指针。

然后就没有然后了。

  1  map:array[0..2100000,'a'..'z']of longint;
  2     t:array[0..2100000]of record
  3                            s:longint;
  4                           end;
  5     root:array[0..500000]of longint;
  6     head,vet,next,dep:array[1..500000]of longint;
  7     f:array[1..550000,0..18]of longint;
  8     len:array[1..500000]of string;
  9     n,i,x,y,tot,tmp,cnt,j,k,q:longint;
 10     zyd,ch1,ch:string;
 11 
 12 procedure add(a,b:longint;c:string);
 13 begin
 14  inc(tot);
 15  next[tot]:=head[a];
 16  vet[tot]:=b;
 17  len[tot]:=c;
 18  head[a]:=tot;
 19 end;
 20 
 21 procedure dfs1(u:longint);
 22 var e,v,i:longint;
 23 begin
 24  for i:=1 to 18 do
 25  begin
 26   if dep[u]<(1<<i) then break;
 27   f[u,i]:=f[f[u,i-1],i-1];
 28  end;
 29  e:=head[u];
 30  while e<>0 do
 31  begin
 32   v:=vet[e];
 33   if v<>f[u,0] then
 34   begin
 35    dep[v]:=dep[u]+1;
 36    f[v,0]:=u;
 37    dfs1(v);
 38   end;
 39   e:=next[e];
 40  end;
 41 end;
 42 
 43 procedure ins(var x:longint;i:longint);
 44 begin
 45  inc(cnt); t[cnt]:=t[x];
 46  map[cnt]:=map[x];
 47  x:=cnt; inc(t[x].s);
 48  if i<=length(zyd) then ins(map[x,zyd[i]],i+1);
 49 end;
 50 
 51 function query(a,b,c,i:longint):longint;
 52 begin
 53 // writeln(a,' ',b,' ',c);
 54  if i>length(zyd) then exit(t[a].s+t[b].s-t[c].s*2);
 55  exit(query(map[a,zyd[i]],map[b,zyd[i]],map[c,zyd[i]],i+1));
 56 end;
 57 
 58 procedure dfs2(u:longint);
 59 var e,v:longint;
 60 begin
 61  e:=head[u];
 62  while e<>0 do
 63  begin
 64   v:=vet[e];
 65   if v<>f[u,0] then
 66   begin
 67    root[v]:=root[u];
 68    zyd:=len[e];
 69    ins(root[v],1);
 70    dfs2(v);
 71   end;
 72   e:=next[e];
 73  end;
 74 end;
 75 
 76 procedure swap(var x,y:longint);
 77 var t:longint;
 78 begin
 79  t:=x; x:=y; y:=t;
 80 end;
 81 
 82 function lca(x,y:longint):longint;
 83 var i,d:longint;
 84 begin
 85  if dep[x]<dep[y] then swap(x,y);
 86  d:=dep[x]-dep[y];
 87  for i:=0 to 18 do
 88   if d and (1<<i)>0 then x:=f[x,i];
 89  for i:=18 downto 0 do
 90   if f[x,i]<>f[y,i] then
 91   begin
 92    x:=f[x,i]; y:=f[y,i];
 93   end;
 94  if x=y then exit(x);
 95  exit(f[x,0]);
 96 end;
 97 
 98 begin
 99  assign(input,'strings.in'); reset(input);
100  assign(output,'strings.out'); rewrite(output);
101  readln(n);
102  for i:=1 to n-1 do
103  begin
104   readln(ch);
105   j:=1; x:=0;
106   while (ch[j]>='0')and(ch[j]<='9') do
107   begin
108    x:=x*10+ord(ch[j])-ord('0');
109    inc(j);
110   end;
111   inc(j); y:=0;
112   while (ch[j]>='0')and(ch[j]<='9') do
113   begin
114    y:=y*10+ord(ch[j])-ord('0');
115    inc(j);
116   end;
117   inc(j);
118   ch1:='';
119   for k:=j to length(ch) do ch1:=ch1+ch[k];
120   add(x,y,ch1);
121   add(y,x,ch1);
122  end;
123 
124  //f[1,0]:=1;
125 
126  dfs1(1);
127  dfs2(1);
128  readln(q);
129  for i:=1 to q do
130  begin
131   readln(ch);
132   j:=1; x:=0;
133   while (ch[j]>='0')and(ch[j]<='9') do
134   begin
135    x:=x*10+ord(ch[j])-ord('0');
136    inc(j);
137   end;
138   inc(j); y:=0;
139   while (ch[j]>='0')and(ch[j]<='9') do
140   begin
141    y:=y*10+ord(ch[j])-ord('0');
142    inc(j);
143   end;
144   inc(j);
145   ch1:='';
146   for k:=j to length(ch) do ch1:=ch1+ch[k];
147   tmp:=lca(x,y);
148   zyd:=ch1;
149   writeln(query(root[x],root[y],root[tmp],1));
150  end;
151 
152  close(input);
153  close(output);
154 end.
View Code

 2016.12.25

学会主席树后重写了一遍,感觉异常轻松

因为此题询问的是边上的信息,所以LCA点不会被重复计算,询问时也就不用-1

如果是点则要-1

 

  1 var map:array[0..2100000,'a'..'z']of longint;
  2     t:array[0..2100000]of longint;
  3     root:array[1..500000]of longint;
  4     head,vet,next,dep,flag:array[1..500000]of longint;
  5     f:array[1..550000,0..18]of longint;
  6     len:array[1..500000]of string;
  7     n,i,x,y,tot,tmp,cnt,j,k,s,m,l,q:longint;
  8     ch,h:string;
  9 
 10 
 11 procedure swap(var x,y:longint);
 12 var t:longint;
 13 begin
 14  t:=x; x:=y; y:=t;
 15 end;
 16 
 17 procedure add(a,b:longint;c:string);
 18 begin
 19  inc(tot);
 20  next[tot]:=head[a];
 21  vet[tot]:=b;
 22  len[tot]:=c;
 23  head[a]:=tot;
 24 end;
 25 
 26 function lca(x,y:longint):longint;
 27 var d,i:longint;
 28 begin
 29  if dep[x]<dep[y] then swap(x,y);
 30  d:=dep[x]-dep[y];
 31  for i:=0 to 18 do
 32   if d and (1<<i)>0 then x:=f[x,i];
 33  for i:=18 downto 0 do
 34   if f[x,i]<>f[y,i] then
 35   begin
 36    x:=f[x,i]; y:=f[y,i];
 37   end;
 38  if x=y then exit(x);
 39  exit(f[x,0]);
 40 end;
 41 
 42 procedure build(i:longint;var p:longint);
 43 begin
 44  inc(cnt); t[cnt]:=t[p];
 45  map[cnt]:=map[p];
 46  p:=cnt; inc(t[p]);
 47  if i<=l then build(i+1,map[p,h[i]]);
 48 end;
 49 
 50 procedure dfs(u:longint);
 51 var e,v,i:longint;
 52 begin
 53  for i:=1 to 18 do
 54  begin
 55   if dep[u]<(1<<i) then break;
 56   f[u,i]:=f[f[u,i-1],i-1];
 57  end;
 58  flag[u]:=1; e:=head[u];
 59  while e<>0 do
 60  begin
 61   v:=vet[e];
 62   if flag[v]=0 then
 63   begin
 64    dep[v]:=dep[u]+1;
 65    f[v,0]:=u;
 66    root[v]:=root[u];
 67    h:=len[e]; l:=length(h);
 68    build(1,root[v]);
 69    dfs(v);
 70   end;
 71   e:=next[e];
 72  end;
 73 end;
 74 
 75 function query(x,y,z,i:longint):longint;
 76 begin
 77  if i=l+1 then exit(t[x]+t[y]-2*t[z]);
 78  exit(query(map[x,h[i]],map[y,h[i]],map[z,h[i]],i+1));
 79 end;
 80 
 81 begin
 82  assign(input,'bzoj4477.in'); reset(input);
 83  assign(output,'bzoj4477.out'); rewrite(output);
 84  readln(n);
 85  for i:=1 to n-1 do
 86  begin
 87   readln(ch);
 88   k:=length(ch); x:=0; y:=0; h:='';
 89   s:=1;
 90   for j:=1 to k do
 91   begin
 92    if ch[j]=' ' then begin inc(s); continue; end;
 93    if s=1 then x:=x*10+ord(ch[j])-ord('0');
 94    if s=2 then y:=y*10+ord(ch[j])-ord('0');
 95    if s=3 then h:=h+ch[j];
 96   end;
 97   add(x,y,h);
 98   add(y,x,h);
 99  end;
100  dfs(1);
101  readln(m);
102  for i:=1 to m do
103  begin
104   readln(ch);
105   k:=length(ch); x:=0; y:=0; s:=1; h:='';
106   for j:=1 to k do
107   begin
108    if ch[j]=' ' then begin inc(s); continue; end;
109    if s=1 then x:=x*10+ord(ch[j])-ord('0');
110    if s=2 then y:=y*10+ord(ch[j])-ord('0');
111    if s=3 then h:=h+ch[j];
112   end;
113   q:=lca(x,y);
114   l:=length(h);
115   writeln(query(root[x],root[y],root[q],1));
116  end;
117  close(input);
118  close(output);
119 end.

 

posted on 2015-12-03 20:18  myx12345  阅读(281)  评论(0编辑  收藏  举报

导航