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字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...
随机推荐
- BestCoder Round #60 1002
Problem Description You are given two numbers NNN and MMM. Every step you can get a new NNN in the w ...
- poj1789 Truck History
Truck History Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 20768 Accepted: 8045 De ...
- Bmob用户管理操作
注册用户 BmobUser bu = new BmobUser(); bu.setUsername("sendi"); bu.setPassword("123456&qu ...
- Continuous Subarray Sum
Given an integer array, find a continuous subarray where the sum of numbers is the biggest. Your cod ...
- Python多线程(1)——介绍
Python对多线程提供了很好的支持,Python中多线程相关的模块包括:thread,threading,Queue.可以方便地支持创建线程.互斥锁.信号量.同步等特性. 1. thread:多线程 ...
- web iphone css 兼容性
解决IPHONE网页兼容(部分字号变大): body{-webkit-text-size-adjust:none;}
- Shallow Size 和 Retained Size
所有包含Heap Profling功能的工具(MAT, Yourkit, JProfiler, TPTP等)都会使用到两个名词,一个是Shallow Size,另一个是 Retained Size. ...
- 分类and分类延展
1.Category简介 Category,又称为类别&类目&分类,是OC特有语法,在不修改原有类的基础上增加新的方法,一个庞大的类可以多人来分模块开发,有助于团队合作,或者对当前类方 ...
- cf455a(简单dp)
题意:给出一个长度为n的数列,元素为a1, a2, ...an:删除ai,ai+1,ai-1 可以得到ai积分,输出最多可以得到多少积分: 题解:开一个数组a存取数列,a[i]表示元素i的个数,所以删 ...
- Android之圆角矩形
安卓圆角矩形的定义 在drawable文件夹下,定义corner.xml <?xml version="1.0" encoding="utf-8"?> ...