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字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...
随机推荐
- RHEL 6.0使用CentOS yum源
引言:由于RHEL的yum在线更新是收费的,如果没有注册的话是不能使用的,即不能在线安装软件.在这种情况下,想使用RHEL系统,还想用yum源来在线安装软件,有没有办法?答案是有办法,请往下看! 1. ...
- Unity3d iOS基本优化和高级优化
原地址:http://www.cocoachina.com/bbs/read.php?tid=70395&page=1 分享看见的2篇好文.简单翻译了一下并且放出原文 http://www.c ...
- 用poi框架进行批量导入导出实例
Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程式对Microsoft Office格式档案读和写的功能.我们这里使用poi对数据库中的数据进行批量导出,以及 ...
- POJ 矩阵相乘 (随机化算法-舍伍德(Sherwood))
周三的算法课,主要讲了随机化算法,介绍了拉斯维加斯算法,简单的理解了为什么要用随机化算法,随机化算法有什么好处. 在处理8皇后问题的时候,穷举法是最费时的,回朔比穷举好点,而当数据量比较大的时候,如1 ...
- SQL面试积累
以下题目都在MySQL上测试可行,有疏漏或有更优化的解决方法的话欢迎大家提出,我会持续更新的:) 有三个表,如果学生缺考,那么在成绩表中就不存在这个学生的这门课程成绩的记录,写一段SQL语句,检索出每 ...
- 基本二叉搜索树的第K小元素
#include<stdio.h> #include<stdlib.h> typedef struct node *btlink; struct node { int data ...
- thinkcentre m8380t黑屏 解决办法
问题: 开机后,显示器上显示“无信号输入”,一直黑屏,但是主机的风扇.硬盘声音都正常. 解决办法: 把vga线等加紧了一些,屏幕还是不亮,然后我关掉插排电源,给cmos放了电,再重启就可以了. 这时需 ...
- Android PullToRefreshListView上拉刷新和下拉刷新
PullToRefreshListView实现上拉和下拉刷新有两个步骤: 1.设置刷新方式 pullToRefreshView.setMode(PullToRefreshBase.Mode.BOTH) ...
- Android Volley获取json格式的数据
为了让Android能够快速地访问网络和解析通用的数据格式Google专门推出了Volley库,用于Android系统的网络传输.volley库可以方便地获取远程服务器的图片.字符串.json对象和j ...
- mybatis存入数据库后没有时分秒时间不全只有年月日
对于Ibatis操作Date/Time/DateTime,总结如下: 将pojo的属性类型设置为java.sql.Date(或java.sql.Time, java.sql.Timestamp),此时 ...