【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.
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.
null