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字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...
随机推荐
- meanshift和camshift
参考:http://www.cnblogs.com/tornadomeet/archive/2012/03/15/2398769.html 照着这位大神的代码运行了一下,发现meanshift的跟踪效 ...
- hdu1151 二分图(无回路有向图)的最小路径覆盖 Air Raid
欢迎参加——BestCoder周年纪念赛(高质量题目+多重奖励) Air Raid Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65 ...
- 替罪羊树—BZOJ3224: Tyvj 1728 普通平衡树
冬令营被平衡树坑了之后,打算苦练一番数据结构(QAQ). 先是打了一下想学好久的替罪羊树. 替罪羊树实现方法很简单,就是在不满足平衡条件的时候暴力重构子树. 调试小结: 1.删除操作分两类情况:如果某 ...
- fsck检查和修复文件系统
重视:fsck不能乱用.先要把文件系统umount掉,然后检查.最好启动到单用户模式下fsck. 常见的5种损坏类型 1 未被引用的inode 2 难以置信的超大链接数 3 没有记录在磁盘块映射表中的 ...
- Netbeans 配置英文和默认utf-8编码
JAVA SDK 下载地址 http://www.oracle.com/technetwork/java/javase/downloads 解决办法: 进入netbeans 6.5\etc ,其中ne ...
- Android 和iOS 创建本地通知
1 Android 中的发送本地通知的逻辑如下 先实例化Notification.Builder,再用builder创建出具体的Notification,创建时要指定好启动用的PendingInten ...
- CPinyin unicode汉字查找拼音(支持多音字)
下载代码 --------------------------------------------------------------------------------- 虽然很笨的办法,却非常有效 ...
- codeforces A. New Year Candles 解题报告
题目链接:http://codeforces.com/problemset/problem/379/A 题目意思:给定a支蜡烛(每支蜡烛可以燃烧1小时),可以在燃尽的a支蜡烛中看能组成多少组b支蜡烛, ...
- delete 类对象指针的注意事项]
http://blog.csdn.net/infoworld/article/details/45560219 场景:1. C++类有构造和析构函数,析构函数是在类对象被delete时(或局部变量自动 ...
- vector data() [c++11]
Example 12345678910111213141516171819202122 // vector::data #include <iostream> #include <v ...