【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+ ...
随机推荐
- linux系统快捷键使用
本文记录linux系统中快捷键的使用 Ctrl + l 清屏,相当于clear命令Ctrl + o 执行当前命令,并重新显示本命令Ctrl + s 阻止屏幕输出,锁定Ctrl + q 允许屏幕输出Ct ...
- 破解studio 3T
方法一: 打开注册表:regedit 计算机\HKEY_CURRENT_USER\Software\JavaSoft\Prefs\3t\mongochef\enterprise 将里面得数据清零,又是 ...
- vue.js 二 路由懒加载
当项目小的时候,我没考虑要去找这个得解决方案,也幸好现在几乎能迁移的项目都整合在了一个vue的项目里面 才发现编译后的vendor.js变得异常的大,而且几乎在项目每一个页面都需要加载这一个js,项目 ...
- HDwiki 源代码 - 互动百科开源
昨日3.15,在曝光的企业中出现了一家让我好奇的企业(互动百科),一直不敢想百科能独立出来做成一家公司.出于对网站的好奇,今日进入该网站,惊讶的是此公司已经上市(股票代码:835799),在网站的底部 ...
- JZOJ 3509. 【NOIP2013模拟11.5B组】倒霉的小C
3509. [NOIP2013模拟11.5B组]倒霉的小C(beats) (File IO): input:beats.in output:beats.out Time Limits: 1000 ms ...
- day 52 Django基础一之web框架的本质
Django基础一之web框架的本质 django第一天 本节目录 一 web框架的本质及自定义web框架 二 模板渲染JinJa2 三 MVC和MTV框架 四 Django的下载安装 五 基于D ...
- python3 练习题100例 (十三)
题目十三:将一个正整数分解质因数.例如:输入60,打印出60=2*2*3*5. #!/usr/bin/env python3 # -*- coding: utf-8 -*- ""& ...
- A1083 List Grades (25)(25 分)
A1083 List Grades (25)(25 分) Given a list of N student records with name, ID and grade. You are supp ...
- 并查集:HDU5326-Work(并查集比较简单灵活的运用)
Work HDU原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5326 Time Limit: 2000/1000 MS (Java/Others) M ...
- 记忆化搜索:HDU1078-FatMouse and Cheese(记忆化搜索)
FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...