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

此题花费我整整三天的功夫。还在NoiP贴吧发过贴。
最后发现trie树建新节点时信息未完全复制,真是愚蠢之极。
言归正传。
如果我们已经知道了每个点上的trie树那么询问就是sum[x]+sum[y]-sum[lca(x,y)]*2
然后就是trie树变可持久化。
DFS2中插入所有字符串,建立新节点,复制出现次数与trie树的next指针。
然后就没有然后了。
map:array[..,'a'..'z']of longint;
t:array[..]of record
s:longint;
end;
root:array[..]of longint;
head,vet,next,dep:array[..]of longint;
f:array[..,..]of longint;
len:array[..]of string;
n,i,x,y,tot,tmp,cnt,j,k,q:longint;
zyd,ch1,ch:string; procedure add(a,b:longint;c:string);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; procedure dfs1(u:longint);
var e,v,i:longint;
begin
for i:= to do
begin
if dep[u]<(<<i) then break;
f[u,i]:=f[f[u,i-],i-];
end;
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>f[u,] then
begin
dep[v]:=dep[u]+;
f[v,]:=u;
dfs1(v);
end;
e:=next[e];
end;
end; procedure ins(var x:longint;i:longint);
begin
inc(cnt); t[cnt]:=t[x];
map[cnt]:=map[x];
x:=cnt; inc(t[x].s);
if i<=length(zyd) then ins(map[x,zyd[i]],i+);
end; function query(a,b,c,i:longint):longint;
begin
// writeln(a,' ',b,' ',c);
if i>length(zyd) then exit(t[a].s+t[b].s-t[c].s*);
exit(query(map[a,zyd[i]],map[b,zyd[i]],map[c,zyd[i]],i+));
end; procedure dfs2(u:longint);
var e,v:longint;
begin
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>f[u,] then
begin
root[v]:=root[u];
zyd:=len[e];
ins(root[v],);
dfs2(v);
end;
e:=next[e];
end;
end; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; function lca(x,y:longint):longint;
var i,d:longint;
begin
if dep[x]<dep[y] then swap(x,y);
d:=dep[x]-dep[y];
for i:= to do
if d and (<<i)> then x:=f[x,i];
for i:= downto do
if f[x,i]<>f[y,i] then
begin
x:=f[x,i]; y:=f[y,i];
end;
if x=y then exit(x);
exit(f[x,]);
end; begin
assign(input,'strings.in'); reset(input);
assign(output,'strings.out'); rewrite(output);
readln(n);
for i:= to n- do
begin
readln(ch);
j:=; x:=;
while (ch[j]>='')and(ch[j]<='') do
begin
x:=x*+ord(ch[j])-ord('');
inc(j);
end;
inc(j); y:=;
while (ch[j]>='')and(ch[j]<='') do
begin
y:=y*+ord(ch[j])-ord('');
inc(j);
end;
inc(j);
ch1:='';
for k:=j to length(ch) do ch1:=ch1+ch[k];
add(x,y,ch1);
add(y,x,ch1);
end; //f[1,0]:=1; dfs1();
dfs2();
readln(q);
for i:= to q do
begin
readln(ch);
j:=; x:=;
while (ch[j]>='')and(ch[j]<='') do
begin
x:=x*+ord(ch[j])-ord('');
inc(j);
end;
inc(j); y:=;
while (ch[j]>='')and(ch[j]<='') do
begin
y:=y*+ord(ch[j])-ord('');
inc(j);
end;
inc(j);
ch1:='';
for k:=j to length(ch) do ch1:=ch1+ch[k];
tmp:=lca(x,y);
zyd:=ch1;
writeln(query(root[x],root[y],root[tmp],));
end; close(input);
close(output);
end.
2016.12.25
学会主席树后重写了一遍,感觉异常轻松
因为此题询问的是边上的信息,所以LCA点不会被重复计算,询问时也就不用-1
如果是点则要-1
var map:array[..,'a'..'z']of longint;
t:array[..]of longint;
root:array[..]of longint;
head,vet,next,dep,flag:array[..]of longint;
f:array[..,..]of longint;
len:array[..]of string;
n,i,x,y,tot,tmp,cnt,j,k,s,m,l,q:longint;
ch,h:string; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure add(a,b:longint;c:string);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; function lca(x,y:longint):longint;
var d,i:longint;
begin
if dep[x]<dep[y] then swap(x,y);
d:=dep[x]-dep[y];
for i:= to do
if d and (<<i)> then x:=f[x,i];
for i:= downto do
if f[x,i]<>f[y,i] then
begin
x:=f[x,i]; y:=f[y,i];
end;
if x=y then exit(x);
exit(f[x,]);
end; procedure build(i:longint;var p:longint);
begin
inc(cnt); t[cnt]:=t[p];
map[cnt]:=map[p];
p:=cnt; inc(t[p]);
if i<=l then build(i+,map[p,h[i]]);
end; procedure dfs(u:longint);
var e,v,i:longint;
begin
for i:= to do
begin
if dep[u]<(<<i) then break;
f[u,i]:=f[f[u,i-],i-];
end;
flag[u]:=; e:=head[u];
while e<> do
begin
v:=vet[e];
if flag[v]= then
begin
dep[v]:=dep[u]+;
f[v,]:=u;
root[v]:=root[u];
h:=len[e]; l:=length(h);
build(,root[v]);
dfs(v);
end;
e:=next[e];
end;
end; function query(x,y,z,i:longint):longint;
begin
if i=l+ then exit(t[x]+t[y]-*t[z]);
exit(query(map[x,h[i]],map[y,h[i]],map[z,h[i]],i+));
end; begin
assign(input,'bzoj4477.in'); reset(input);
assign(output,'bzoj4477.out'); rewrite(output);
readln(n);
for i:= to n- do
begin
readln(ch);
k:=length(ch); x:=; y:=; h:='';
s:=;
for j:= to k do
begin
if ch[j]=' ' then begin inc(s); continue; end;
if s= then x:=x*+ord(ch[j])-ord('');
if s= then y:=y*+ord(ch[j])-ord('');
if s= then h:=h+ch[j];
end;
add(x,y,h);
add(y,x,h);
end;
dfs();
readln(m);
for i:= to m do
begin
readln(ch);
k:=length(ch); x:=; y:=; s:=; h:='';
for j:= to k do
begin
if ch[j]=' ' then begin inc(s); continue; end;
if s= then x:=x*+ord(ch[j])-ord('');
if s= then y:=y*+ord(ch[j])-ord('');
if s= then h:=h+ch[j];
end;
q:=lca(x,y);
l:=length(h);
writeln(query(root[x],root[y],root[q],));
end;
close(input);
close(output);
end.
【BZOJ4477】字符串树(可持久化Trie)的更多相关文章
- BZOJ4477[Jsoi2015]字符串树——可持久化trie树
题目描述 萌萌买了一颗字符串树的种子,春天种下去以后夏天就能长出一棵很大的字符串树.字符串树很奇特,树枝上都密密麻麻写满了字符串,看上去很复杂的样子.[问题描述]字符串树本质上还是一棵树,即N个节点N ...
- luogu P6088 [JSOI2015]字符串树 可持久化trie 线段树合并 树链剖分 trie树
LINK:字符串树 先说比较简单的正解.由于我没有从最简单的考虑答案的角度思考 所以... 下次还需要把所有角度都考察到. 求x~y的答案 考虑 求x~根+y~根-2*lca~根的答案. 那么问题变成 ...
- [bzoj4477 Jsoi2015]字符串树 (可持久化trie)
传送门 Solution 复习下tire( ̄▽ ̄)/ 裸的可持久化tire,我用树剖求了下LCA Code #include <cstdio> #include <cstring&g ...
- BZOJ 4477: [Jsoi2015]字符串树 可持久化trie树
这个是真——可持久化字典树..... code: #include <bits/stdc++.h> #define N 100006 #define setIO(s) freopen(s& ...
- 4.24 省选模拟赛 欧珀瑞特 主席树 可持久化trie树
很容易的一道题目.大概.不过我空间计算失误MLE了 我草草的计算了一下没想到GG了. 关键的是 我学了一个dalao的空间回收的方法 但是弄巧成拙了. 题目没有明确指出 在任意时刻数组长度为有限制什么 ...
- 【BZOJ-4212】神牛的养成计划 Trie树 + 可持久化Trie树
4212: 神牛的养成计划 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 136 Solved: 27[Submit][Status][Discus ...
- 【BZOJ4212】神牛的养成计划 Trie树+可持久化Trie树
[BZOJ4212]神牛的养成计划 Description Hzwer成功培育出神牛细胞,可最终培育出的生物体却让他大失所望...... 后来,他从某同校女神 牛处知道,原来他培育的细胞发生了基因突变 ...
- P4585-[FJOI2015]火星商店问题【线段树,可持久化Trie】
正题 题目链接:https://www.luogu.com.cn/problem/P4585 题目大意 \(n\)个集合,开始每个集合中有一个数字. 开启新的一天并且往集合\(s\)中插入数字\(v\ ...
- BZOJ4477 JSOI2015字符串树(可持久化trie)
树上建可持久化trie即可,有点过于裸了.darkbzoj过了然而在bzoj一直wa,不知道哪有锅. #include<iostream> #include<cstdio> # ...
- 【BZOJ4477】[JSOI2015]字符串树(Trie树)
[BZOJ4477][JSOI2015]字符串树(Trie树) 题面 BZOJ 题解 对于每个点维护其到根节点的所有字符串构成的\(Trie\),显然可持久化一下就很好写了. 然后每次询问就是\(u+ ...
随机推荐
- js获取整型数组最大值、最小值、平均值
---恢复内容开始--- let values = [];//数组(整型数字) //获取数组最大值function arrMaxNum(arr){ var maxNum = null; for (va ...
- k8s的secret基本概念及案例
secret相对于configMap,功能上是相似的但是secret是以其他编码方式去记录配置信息的,但是也可以被解读,只不过有技术门槛,不是那么容易就被解读.使用base64可以解码:echo ** ...
- goaccess实现实时监控
一.实现后台实时监控 goaccess -p /usr/local/etc/goaccess/goaccess.conf /var/log/nginx/access.log -a -o /usr/sh ...
- 使用 CAST
使用 CAST: CAST ( expression AS data_type ) 使用 CONVERT: CONVERT (data_type[(length)], expression [, st ...
- B1020 月饼(25 分)
B1020 月饼(25 分) 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼.现给定所有种类月饼的库存量.总售价.以及市场的最大需求量,请你计算可以获得的最大收益是多少. 注意 ...
- 百度之星初赛A 今夕何夕
今夕何夕 今天是2017年8月6日,农历闰六月十五. 小度独自凭栏,望着一轮圆月,发出了"今夕何夕,见此良人"的寂寞感慨. 为了排遣郁结,它决定思考一个数学问题:接下来最近的哪一年 ...
- 51nod_1255字典序最小的子序列
作为贪心算法的某道例题,赶脚药丸啊..这么简单的代码重构第三遍才过... 首先是贪心算法思想, 1,证明贪心算法有效性:贪心策略,使用栈结构实现,遍历输入串中所有元素,对于某个元素有如下两种情况: 情 ...
- 使用Spark Streaming + Kudu + Impala构建一个预测引擎
随着用户使用天数的增加,不管你的业务是扩大还是缩减了,为什么你的大数据中心架构保持线性增长的趋势?很明显需要一个稳定的基本架构来保障你的业务线.当你的客户处在休眠期,或者你的业务处在淡季,你增加的计算 ...
- IOS开发学习笔记020-练习总结
自己做了一遍,现在再复习一下,总结一下. 最终效果如下 1.新建一个工程Single View Application 总体如下 不过要关闭自动布局功能 这是按下设置按钮显示的界面默认 ...
- CTF 两道web整数溢出题目(猫咪银行和ltshop)
①猫咪银行: (2018中科大hackgame) 一开始给十个CTB,而flag需要20个CTB,我们需要理财赚够20个. 理财是只能买入TDSU才可以获得收益.我们先上来直接把CTB全部换成TDSU ...