就一篇题解:

BZOJ3467 : Crash和陶陶的游戏 - weixin_34248487的博客 - CSDN博客

1.离线,建出Atrie树;B树的倍增哈希数组,节点按照到根路径字典序排序

2.处理A节点对应前缀对应B中的极长可以匹配的区间。在父亲节点区间内二分即可

3.更新答案:

①加入A点,找区间中B中已经出现点个数。树状数组

②加入B点,本质是B到根的字符串放在trie最大匹配长度,二分,哈希表存A树是否有这个前缀,得到的长度就是当前匹配长度。

直上直下的链本质是字符串的前缀后缀。

动态更新hash很难,就离线,在可能贡献的集合内找到当前出现的。

假装有代码.jpg

这个是两个logn的

可以变成一个logn!

sort是不必要的,

对于②B树点对trie的影响,不妨直接倍增+hash找到最长的匹配位置y,在y的位置++,然后①时候子树查询即可!

通过提前打好标记使得不用同时考虑很多!

(类似预处理)

还有可能一个点有多个c儿子,要合并成一个。①的时候整个子树++,表示到根的路径上多了一个点,②的时候,匹配最长位置单点查询这个值

两个树状数组

注意,unsigned long long哈希

单模数随便rand就卡掉了

  1. #include<bits/stdc++.h>
  2. #define reg register int
  3. #define il inline
  4. #define fi first
  5. #define se second
  6. #define mk(a,b) make_pair(a,b)
  7. #define numb (ch^'0')
  8. #define ul unsigned long long
  9. #define ll unsigned long long
  10. using namespace std;
  11. il void rd(int &x){
  12. char ch;x=;bool fl=false;
  13. while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
  14. for(x=numb;isdigit(ch=getchar());x=x*+numb);
  15. (fl==true)&&(x=-x);
  16. }
  17. template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
  18. template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
  19. template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
  20.  
  21. namespace Miracle{
  22. const int N=2e5+;
  23. const ul base=;
  24. const int orz=;
  25.  
  26. struct HA{
  27. int nxt[N],hd[N],cnt;
  28. ul val[N];
  29. int id[N];
  30. void ins(int x,ll h){
  31. int pos=h%orz;
  32. nxt[++cnt]=hd[pos];hd[pos]=cnt;val[cnt]=h;
  33. id[cnt]=x;
  34. }
  35. int query(ll h){
  36. int pos=h%orz;
  37. for(reg i=hd[pos];i;i=nxt[i]){
  38. if(val[i]==h) return id[i];
  39. }
  40. return -;
  41. }
  42. }ha;
  43. //trie
  44. int ch[N][];
  45. int id[N];//is
  46. int n;
  47. int tot;
  48. int lp;
  49. ul pw[(<<)+];
  50. void ins(int x,int c){
  51. ++lp;
  52. x=id[x];
  53. // cout<<" true fa "<<x<<" ch "<<ch[x][c]<<endl;
  54. if(ch[x][c]){
  55. id[lp]=ch[x][c];return;
  56. }
  57. id[lp]=++tot;
  58. ch[x][c]=tot;
  59. }
  60. int dfn[N],df,dfn2[N];
  61. void fin(int x,ul haxi,int d){
  62. dfn[x]=++df;
  63. if(x!=){
  64. ha.ins(x,haxi);
  65. }
  66. for(reg i=;i<;++i){
  67. if(ch[x][i]){
  68. fin(ch[x][i],haxi+(ll)pw[d]*(i+),d+);
  69. }
  70. }
  71. dfn2[x]=df;
  72. }
  73. //B tree
  74. int cur;
  75. struct node{
  76. int nxt,to;
  77. int val;
  78. }e[*N];
  79. int hd[N],cnt;
  80. void add(int x,int y,int z){
  81. e[++cnt].nxt=hd[x];
  82. e[cnt].to=y;
  83. e[cnt].val=z;
  84. hd[x]=cnt;
  85. }
  86. int fa[N][];
  87. ul hsh[N][];
  88. void dfs(int x){
  89. for(reg i=hd[x];i;i=e[i].nxt){
  90. int y=e[i].to;
  91. fa[y][]=x;
  92. hsh[y][]=e[i].val+;
  93. dfs(y);
  94. }
  95. }
  96. //question
  97. struct que{
  98. int typ,fa,c;
  99. int x;
  100. }q[N];
  101.  
  102. int get(int x){
  103. ll now=;
  104. int has=;
  105. int ret=;
  106. for(reg j=;j>=;--j){
  107. if(!fa[x][j]) continue;
  108. ll tmp=((ll)now+pw[has]*hsh[x][j]);
  109. int nc=ha.query(tmp);
  110. if(nc!=-){
  111. ret=nc;
  112. now=tmp;
  113. has+=(<<j);
  114. x=fa[x][j];//shit
  115. }
  116. }
  117. return ret;
  118. }
  119.  
  120. struct treearray{
  121. int f[N];
  122. int n;
  123. void upda(int x,int c){
  124. for(;x<=n;x+=x&(-x)) f[x]+=c;
  125. }
  126. int query(int x){
  127. int ret=;
  128. for(;x;x-=x&(-x)) ret+=f[x];return ret;
  129. }
  130. }t1,t2;
  131. int main(){
  132. rd(n);
  133. char s[];
  134. ++tot;++cur;//start
  135. lp=;
  136. id[]=;
  137.  
  138. ll ans=;
  139. ans=;//1 1
  140. for(reg i=;i<=n;++i){
  141. rd(q[i].typ);rd(q[i].fa);//rd(q[i].c);
  142. scanf("%s",s+);q[i].c=s[]-'a';
  143. if(q[i].typ==){
  144. ins(q[i].fa,q[i].c);
  145. q[i].x=id[lp];
  146. // prt(id,1,lp);
  147. }else{
  148. ++cur;
  149. q[i].x=cur;
  150. add(q[i].fa,cur,q[i].c);
  151. }
  152. // cout<<tot<<" ";
  153. }
  154. // cout<<endl<<endl;
  155. dfs();
  156. // cout<<"after dfs "<<tot<<endl;
  157. // prt(id,1,lp);
  158.  
  159. pw[]=;
  160. for(reg i=;i<=(<<);++i){
  161. pw[i]=(ll)pw[i-]*base;//%mod;
  162. }
  163. for(reg j=;j<=;++j){
  164. for(reg i=;i<=cur;++i){
  165. fa[i][j]=fa[fa[i][j-]][j-];
  166. hsh[i][j]=((ll)hsh[i][j-]+(ll)hsh[fa[i][j-]][j-]*pw[<<(j-)]);//%mod)%mod;
  167. }
  168. }
  169. // cout<<"after bezeng "<<endl;
  170. fin(,,);
  171. // cout<<" after fin "<<endl;
  172. t1.n=t2.n=tot;
  173. // cout<<" tot "<<tot<<endl;
  174. // prt(dfn,1,tot);
  175. // cout<<" dfn2-------------------------- "<<endl;
  176. // prt(dfn2,1,tot);
  177. int tc=,tb=;
  178. for(reg i=;i<=n;++i){
  179. if(q[i].typ==){//add trie
  180. ++tc;
  181. // cout<<"trie "<<endl;
  182. int x=q[i].x;//ch[id[q[i].fa]][q[i].c];
  183. // cout<<"x "<<x<<" tc "<<tc<<endl;
  184. ans+=t1.query(dfn2[x])-t1.query(dfn[x]-);
  185. t2.upda(dfn[x],);t2.upda(dfn2[x]+,-);
  186. }else{//add B tree
  187. ++tb;
  188. // cout<<" Btree "<<endl;
  189. // cout<<" x "<<q[i].x<<endl;
  190. int y=get(q[i].x);
  191. // cout<<" y "<<y<<" tb "<<tb<<" dfn "<<dfn[y]<<endl;
  192. if(y){
  193. ans+=t2.query(dfn[y]);
  194. t1.upda(dfn[y],);
  195. }
  196. ++ans;
  197. }
  198. printf("%lld\n",ans);
  199. }
  200. return ;
  201. }
  202.  
  203. }
  204. signed main(){
  205. // freopen("5.in","r",stdin);
  206. // freopen("my.out","w",stdout);
  207. Miracle::main();
  208. return ;
  209. }
  210.  
  211. /*
  212. Author: *Miracle*
  213. Date: 2019/3/26 18:56:24
  214. */

bzoj3467: Crash和陶陶的游戏的更多相关文章

  1. P1676陶陶吃苹果 - vijos

    描述 curimit知道陶陶很喜欢吃苹果.于是curimit准备在陶陶生日的时候送给他一棵苹果树. curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上有c[i]个苹果, ...

  2. bzoj 2402: 陶陶的难题II 二分答案维护凸包

    2402: 陶陶的难题II Time Limit: 40 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 68  Solved: 45[Submi ...

  3. bzoj 2401: 陶陶的难题I 数论

    2401: 陶陶的难题I Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 89  Solved: 24[Submit][Status] Descript ...

  4. 武汉科技大学ACM:1007: 陶陶摘苹果

    Problem Description 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹 ...

  5. 洛谷-陶陶摘苹果(升级版)-BOSS战-入门综合练习1

    题目描述 Description 又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果,这次她有一个a公分的椅子.当他手够不着时,他会站到椅子上再试试. 这次与NOIp2005普及组第一题不同 ...

  6. NOIP2005-普及组复赛-第一题-陶陶摘苹果

    题目描述 Description 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳 ...

  7. noip普及组2005 陶陶摘苹果

    陶陶摘苹果 描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 现在 ...

  8. 2719:陶陶摘苹果-poj

    2719:陶陶摘苹果 总时间限制:  1000ms 内存限制:  65536kB 描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米 ...

  9. [Vijos 1676] 陶陶吃苹果

    Description curimit知道陶陶很喜欢吃苹果.于是curimit准备在陶陶生日的时候送给他一棵苹果树. curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上 ...

随机推荐

  1. Quartz 定时任务时间设置

    转自https://blog.csdn.net/zdx1515888659/article/details/79158169 quartz定时任务时间设置: 这些星号由左到右按顺序代表 : * * * ...

  2. Unable to handle kernel paging request at virtual address

    1.Unable to handle kernel paging request at virtual address 00000000 =====>越出内核地址空间范围,原因是由于使用空NUL ...

  3. hdu1875(最小生成树prime)

    思路:一开始想用贪心来着,发现贪心有缺陷,然后就用了最小生成树来写,这里用了prime算法,首先,先建个图,两点之间的边的权值就是两个点的距离,然后直接prime模板 代码 #include<i ...

  4. gym-101350M

    题意:给你一堆货币汇率,再给你一堆货币,算下值多少钱: 思路:直接map搞定: #include<iostream> #include<algorithm> #include& ...

  5. HTC Vive 基础入门 基于Unity3D引擎

    任务2: 01-概述 07:08 任务3: 02-HTC Vive设备的安装 08:33 任务4: 03-下载Steam与SteamVR 03:05 任务5: 04-使用Steam VR 调试设备 1 ...

  6. 解决Docker容器中不能用vim编辑文件

    更新来源: apt-get update 安装vim apt-get install -y vim 参考链接:https://blog.csdn.net/wangxinxinsj/article/de ...

  7. BZOJ2463[中山市选2009]谁能赢呢?——博弈论

    题目描述 小明和小红经常玩一个博弈游戏.给定一个n×n的棋盘,一个石头被放在棋盘的左上角.他们轮流移动石头.每一回合,选手只能把石头向上,下,左,右四个方向移动一格,并且要求移动到的格子之前不能被访问 ...

  8. Goldbach's Conjecture POJ - 2262 线性欧拉筛水题 哥德巴赫猜想

    题意 哥德巴赫猜想:任一大于2的数都可以分为两个质数之和 给一个n 分成两个质数之和 线行筛打表即可 可以拿一个数组当桶标记一下a[i]  i这个数是不是素数  在线性筛后面加个装桶循环即可 #inc ...

  9. Codeforces Global Round 2 D. Frets On Fire (动态开点线段树,沙雕写法)

    题目链接:D. Frets On Fire 思路:明明可以离散化+二分写,思路硬是歪到了线段树上,自闭了,真实弟弟,怪不得其他人过得那么快 只和查询的区间长度有关系,排完序如果相邻的两个点的差值小于等 ...

  10. hdu 5510 Bazinga (KMP+暴力标记)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5510 思路: 一开始直接用KMP莽了发,超时了,后面发现如果前面的字符串被后面的字符串包含,那么我们就 ...