将输入的Trie建成AC自动机,并建出fail树。

那么操作1等价于在给定点的子树的并集里都加1。

操作2等价于查询给定点到根节点路径的并集的权值和。

求出DFS序后,对于操作1,将点按进入时间戳从小到大排序,然后求出并集,进行区间修改即可。

对于操作2,构造给定点集的虚树,在虚树的每一条边上询问权值和,累加起来即可。

对于子树修改,链查询,可以使用4棵树状数组维护。

时间复杂度$O((m+k)\log n)$。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #define N 100010
  4. using namespace std;
  5. typedef long long ll;
  6. int Case,n,Q,i,j,x,op,ch[N][26],f[N],g[N],nxt[N];
  7. int d[N],size[N],son[N],top[N],st[N],en[N],dfn;
  8. int m,q[N],a[N],tot,t,vis[N];
  9. struct BIT{
  10. int n,s[N<<1],a[N<<1];ll b[N<<1];
  11. inline void init(int x){n=x;for(int i=1;i<=n;i++)a[i]=b[i]=s[i]=0;}
  12. 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];}
  13. inline ll ask(int x){
  14. int t0=0;ll t1=0;
  15. for(int i=x;i;i-=i&-i)t0+=a[i],t1+=b[i];
  16. return 1LL*s[x]*t0-t1;
  17. }
  18. inline void add(int x,int y){modify(x,1),modify(y+1,-1);}
  19. }ti,to;
  20. 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';}
  21. inline int getch(){char c;while(!(((c=getchar())>='a')&&(c<='z')));return c;}
  22. inline void make(){
  23. int h=1,t=0,i,j,x;
  24. for(i=0;i<26;i++)if(ch[1][i])f[q[++t]=ch[1][i]]=1;else ch[1][i]=1;
  25. 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];
  26. }
  27. void dfs(int x){
  28. d[x]=d[f[x]]+1,size[x]=1,son[x]=0;
  29. for(int i=g[x];i;i=nxt[i]){
  30. dfs(i),size[x]+=size[i];
  31. if(size[i]>size[son[x]])son[x]=i;
  32. }
  33. }
  34. void dfs2(int x,int y){
  35. top[x]=y;st[x]=++dfn;
  36. if(son[x])dfs2(son[x],y);
  37. for(int i=g[x];i;i=nxt[i])if(i!=son[x])dfs2(i,i);
  38. en[x]=++dfn;
  39. }
  40. inline int lca(int x,int y){
  41. for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
  42. return d[x]<d[y]?x:y;
  43. }
  44. inline int cmp(int x,int y){return st[x]<st[y];}
  45. int main(){
  46. read(Case);
  47. while(Case--){
  48. read(n);
  49. for(i=2;i<=n;i++)read(x),ch[x][getch()-'a']=i;
  50. make();
  51. for(i=2;i<=n;i++)nxt[i]=g[f[i]],g[f[i]]=i;
  52. dfs(1),dfs2(1,1);
  53. ti.init(dfn),to.init(dfn);
  54. for(i=1;i<=n;i++)ti.s[st[i]]=1,to.s[en[i]]=-1;
  55. for(i=2;i<=dfn;i++)ti.s[i]+=ti.s[i-1],to.s[i]+=to.s[i-1];
  56. read(Q);
  57. while(Q--){
  58. read(op),read(m);
  59. if(op==1){
  60. for(i=0;i<m;i++)read(a[i]);
  61. for(sort(a,a+m,cmp),j=i=0;i<m;i++)if(st[a[i]]>j){
  62. ti.add(st[a[i]],en[a[i]]);
  63. to.add(st[a[i]],en[a[i]]);
  64. j=en[a[i]];
  65. }
  66. }else{
  67. for(tot=i=0;i<m;i++){
  68. read(x);
  69. if(!vis[x])vis[a[++tot]=x]=1;
  70. }
  71. if(!vis[1])vis[a[++tot]=1]=1;
  72. m=tot,sort(a+1,a+m+1,cmp);
  73. for(i=1;i<m;i++)if(!vis[x=lca(a[i],a[i+1])])vis[a[++tot]=x]=1;
  74. m=tot,sort(a+1,a+m+1,cmp);
  75. ll ans=ti.ask(1);
  76. for(q[t=1]=a[1],i=2;i<=m;q[++t]=a[i++]){
  77. while(st[a[i]]<st[q[t]]||en[a[i]]>en[q[t]])t--;
  78. ans+=ti.ask(st[a[i]])+to.ask(st[a[i]])-ti.ask(st[q[t]])-to.ask(st[q[t]]);
  79. }
  80. for(i=1;i<=m;i++)vis[a[i]]=0;
  81. printf("%lld\n",ans);
  82. }
  83. }
  84. for(dfn=0,i=1;i<=n;i++)for(f[i]=g[i]=j=0;j<26;j++)ch[i][j]=0;
  85. }
  86. return 0;
  87. }

  

BZOJ3906 : Trie的更多相关文章

  1. 基于trie树做一个ac自动机

    基于trie树做一个ac自动机 #!/usr/bin/python # -*- coding: utf-8 -*- class Node: def __init__(self): self.value ...

  2. 基于trie树的具有联想功能的文本编辑器

    之前的软件设计与开发实践课程中,自己构思的大作业题目.做的具有核心功能,但是还欠缺边边角角的小功能和持久化数据结构,先放出来,有机会一点点改.github:https://github.com/chu ...

  3. [LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)

    Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs ar ...

  4. hihocoder-1014 Trie树

    hihocoder 1014 : Trie树 link: https://hihocoder.com/problemset/problem/1014 题意: 实现Trie树,实现对单词的快速统计. # ...

  5. 【BZOJ-2938】病毒 Trie图 + 拓扑排序

    2938: [Poi2000]病毒 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 609  Solved: 318[Submit][Status][Di ...

  6. Poj The xor-longest Path 经典题 Trie求n个数中任意两个异或最大值

    Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 5646   Accepted: 1226 Description In an ...

  7. 二分+DP+Trie HDOJ 5715 XOR 游戏

    题目链接 XOR 游戏 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  8. 【hihoCoder】1036 Trie图

    题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...

  9. 萌新笔记——C++里创建 Trie字典树(中文词典)(一)(插入、遍历)

    萌新做词典第一篇,做得不好,还请指正,谢谢大佬! 写了一个词典,用到了Trie字典树. 写这个词典的目的,一个是为了压缩一些数据,另一个是为了尝试搜索提示,就像在谷歌搜索的时候,打出某个关键字,会提示 ...

随机推荐

  1. RHEL 6.0使用CentOS yum源

    引言:由于RHEL的yum在线更新是收费的,如果没有注册的话是不能使用的,即不能在线安装软件.在这种情况下,想使用RHEL系统,还想用yum源来在线安装软件,有没有办法?答案是有办法,请往下看! 1. ...

  2. Unity3d iOS基本优化和高级优化

    原地址:http://www.cocoachina.com/bbs/read.php?tid=70395&page=1 分享看见的2篇好文.简单翻译了一下并且放出原文 http://www.c ...

  3. 用poi框架进行批量导入导出实例

    Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程式对Microsoft Office格式档案读和写的功能.我们这里使用poi对数据库中的数据进行批量导出,以及 ...

  4. POJ 矩阵相乘 (随机化算法-舍伍德(Sherwood))

    周三的算法课,主要讲了随机化算法,介绍了拉斯维加斯算法,简单的理解了为什么要用随机化算法,随机化算法有什么好处. 在处理8皇后问题的时候,穷举法是最费时的,回朔比穷举好点,而当数据量比较大的时候,如1 ...

  5. SQL面试积累

    以下题目都在MySQL上测试可行,有疏漏或有更优化的解决方法的话欢迎大家提出,我会持续更新的:) 有三个表,如果学生缺考,那么在成绩表中就不存在这个学生的这门课程成绩的记录,写一段SQL语句,检索出每 ...

  6. 基本二叉搜索树的第K小元素

    #include<stdio.h> #include<stdlib.h> typedef struct node *btlink; struct node { int data ...

  7. thinkcentre m8380t黑屏 解决办法

    问题: 开机后,显示器上显示“无信号输入”,一直黑屏,但是主机的风扇.硬盘声音都正常. 解决办法: 把vga线等加紧了一些,屏幕还是不亮,然后我关掉插排电源,给cmos放了电,再重启就可以了. 这时需 ...

  8. Android PullToRefreshListView上拉刷新和下拉刷新

    PullToRefreshListView实现上拉和下拉刷新有两个步骤: 1.设置刷新方式 pullToRefreshView.setMode(PullToRefreshBase.Mode.BOTH) ...

  9. Android Volley获取json格式的数据

    为了让Android能够快速地访问网络和解析通用的数据格式Google专门推出了Volley库,用于Android系统的网络传输.volley库可以方便地获取远程服务器的图片.字符串.json对象和j ...

  10. mybatis存入数据库后没有时分秒时间不全只有年月日

    对于Ibatis操作Date/Time/DateTime,总结如下: 将pojo的属性类型设置为java.sql.Date(或java.sql.Time, java.sql.Timestamp),此时 ...