BZOJ3906 : Trie
将输入的Trie建成AC自动机,并建出fail树。
那么操作1等价于在给定点的子树的并集里都加1。
操作2等价于查询给定点到根节点路径的并集的权值和。
求出DFS序后,对于操作1,将点按进入时间戳从小到大排序,然后求出并集,进行区间修改即可。
对于操作2,构造给定点集的虚树,在虚树的每一条边上询问权值和,累加起来即可。
对于子树修改,链查询,可以使用4棵树状数组维护。
时间复杂度$O((m+k)\log n)$。
#include<cstdio>
#include<algorithm>
#define N 100010
using namespace std;
typedef long long ll;
int Case,n,Q,i,j,x,op,ch[N][26],f[N],g[N],nxt[N];
int d[N],size[N],son[N],top[N],st[N],en[N],dfn;
int m,q[N],a[N],tot,t,vis[N];
struct BIT{
int n,s[N<<1],a[N<<1];ll b[N<<1];
inline void init(int x){n=x;for(int i=1;i<=n;i++)a[i]=b[i]=s[i]=0;}
inline void modify(int x,int p){for(int i=x;i<=n;i+=i&-i)a[i]+=p,b[i]+=p*s[x-1];}
inline ll ask(int x){
int t0=0;ll t1=0;
for(int i=x;i;i-=i&-i)t0+=a[i],t1+=b[i];
return 1LL*s[x]*t0-t1;
}
inline void add(int x,int y){modify(x,1),modify(y+1,-1);}
}ti,to;
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
inline int getch(){char c;while(!(((c=getchar())>='a')&&(c<='z')));return c;}
inline void make(){
int h=1,t=0,i,j,x;
for(i=0;i<26;i++)if(ch[1][i])f[q[++t]=ch[1][i]]=1;else ch[1][i]=1;
while(h<=t)for(x=q[h++],i=0;i<26;i++)if(ch[x][i])f[ch[x][i]]=ch[f[x]][i],q[++t]=ch[x][i];else ch[x][i]=ch[f[x]][i];
}
void dfs(int x){
d[x]=d[f[x]]+1,size[x]=1,son[x]=0;
for(int i=g[x];i;i=nxt[i]){
dfs(i),size[x]+=size[i];
if(size[i]>size[son[x]])son[x]=i;
}
}
void dfs2(int x,int y){
top[x]=y;st[x]=++dfn;
if(son[x])dfs2(son[x],y);
for(int i=g[x];i;i=nxt[i])if(i!=son[x])dfs2(i,i);
en[x]=++dfn;
}
inline int lca(int x,int y){
for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
return d[x]<d[y]?x:y;
}
inline int cmp(int x,int y){return st[x]<st[y];}
int main(){
read(Case);
while(Case--){
read(n);
for(i=2;i<=n;i++)read(x),ch[x][getch()-'a']=i;
make();
for(i=2;i<=n;i++)nxt[i]=g[f[i]],g[f[i]]=i;
dfs(1),dfs2(1,1);
ti.init(dfn),to.init(dfn);
for(i=1;i<=n;i++)ti.s[st[i]]=1,to.s[en[i]]=-1;
for(i=2;i<=dfn;i++)ti.s[i]+=ti.s[i-1],to.s[i]+=to.s[i-1];
read(Q);
while(Q--){
read(op),read(m);
if(op==1){
for(i=0;i<m;i++)read(a[i]);
for(sort(a,a+m,cmp),j=i=0;i<m;i++)if(st[a[i]]>j){
ti.add(st[a[i]],en[a[i]]);
to.add(st[a[i]],en[a[i]]);
j=en[a[i]];
}
}else{
for(tot=i=0;i<m;i++){
read(x);
if(!vis[x])vis[a[++tot]=x]=1;
}
if(!vis[1])vis[a[++tot]=1]=1;
m=tot,sort(a+1,a+m+1,cmp);
for(i=1;i<m;i++)if(!vis[x=lca(a[i],a[i+1])])vis[a[++tot]=x]=1;
m=tot,sort(a+1,a+m+1,cmp);
ll ans=ti.ask(1);
for(q[t=1]=a[1],i=2;i<=m;q[++t]=a[i++]){
while(st[a[i]]<st[q[t]]||en[a[i]]>en[q[t]])t--;
ans+=ti.ask(st[a[i]])+to.ask(st[a[i]])-ti.ask(st[q[t]])-to.ask(st[q[t]]);
}
for(i=1;i<=m;i++)vis[a[i]]=0;
printf("%lld\n",ans);
}
}
for(dfn=0,i=1;i<=n;i++)for(f[i]=g[i]=j=0;j<26;j++)ch[i][j]=0;
}
return 0;
}
BZOJ3906 : Trie的更多相关文章
- 基于trie树做一个ac自动机
基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...
- 基于trie树的具有联想功能的文本编辑器
之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...
- [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)
Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...
- hihocoder-1014 Trie树
hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...
- 【BZOJ-2938】病毒 Trie图 + 拓扑排序
2938: [Poi2000]病毒 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 609 Solved: 318[Submit][Status][Di ...
- Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值
Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 5646 Accepted: 1226 Description In an ...
- 二分+DP+Trie HDOJ 5715 XOR 游戏
题目链接 XOR 游戏 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- 【hihoCoder】1036 Trie图
题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...
- 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)
萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...
随机推荐
- 5款Linux最佳照片管理软件
在谈到 Linux 中的应用程序时,对于不同的用户.不同的使用场景以及不同的使用习惯,在同一类应用当中,总会有多种软件可供选择和备选.就 Linux 中的照片管理软件来说,相信此前的 Google P ...
- basic use of sidekiq
参考页面 https://github.com/mperham/sidekiq https://github.com/mperham/sidekiq/wiki/Getting-Started 强烈推荐 ...
- 他们在军训,我在搞 OI(二)
Day 2 7:26 2016/8/25 新的一天又开始了! 走在上学的路上,抬头看看北京少有的蓝天,太阳的威力不再那么明显,甚至输给了挡住它的云朵.迎面吹来了凉爽的风,夏天的燥热,早已无影无踪. 许 ...
- [BZOJ]1016 JSOI2008 最小生成树计数
最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...
- HDU 1087 Super Jumping! Jumping! Jumping! 最大递增子序列
Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 ...
- poj 1007 DNA Sorting 解题报告
题目链接:http://poj.org/problem?id=1007 本题属于字符串排序问题.思路很简单,把每行的字符串和该行字符串统计出的字母逆序的总和看成一个结构体.最后把全部行按照这个总和从小 ...
- Servlet过滤器和监听器
1,Servlet过滤器 <filter> <filter-name>charset</filter-name> <filter-class>org.g ...
- JS操作DOM
[功能:点击按钮显示表单] <html> <head> <meta http-equiv="Content-Type" content="t ...
- Linux 底下使用C 对文件进行遍历
#include <stdio.h>#include <stdlib.h>main (int argc,char *argv[]){char ch;FILE *fp;int i ...
- Cocos2dx实现象棋之布局
开始界面 #ifndef SCENESTART_H #define SCENESTART_H #include "cocos2d.h" #include "SceneGa ...