题意:2种操作:①往集合里添加一个串

②给你四个小串a b c d,问你集合里有几个串S满足S=a+S1+b+c+S2+d的形式。S1 S2可以为空,并且a+S1+b=c+S2+d。

就搞四颗Trie出来,分别存的是

所有S的前半部分 + 所有a串;

所有S的前半部分倒置 + 所有b串倒置;

所有S的后半部分 + 所有c串;

所有S的后半部分倒置 + 所有d串倒置。

这样把问题转化成了询问有几个S串同时在四个串所限制的子树里,用dfs序处理。

另外,由于ab不能交叠,cd不能交叠,所以串的长度要大于等于max(a+b,c+d)*2。

由于我们离线处理,所以对于每次询问,如果其编号为i,所找的串的编号必须小于i。

这样把问题转化成了六维空间内的矩形内点的个数问题,可以用kd-tree解决。

另,开4个Trie是开不下的,只能开一个,重复利用空间……

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<string>
  5. #include<iostream>
  6. using namespace std;
  7. #define N 2000005
  8. #define Q 30005
  9. #define KD 6
  10. int dn,n,root,qp[2][KD];
  11. struct Node
  12. {
  13. int ch[2],w,minn[KD],maxx[KD],p[KD],sumv;
  14. void Init()
  15. {
  16. sumv=w;
  17. ch[0]=ch[1]=0;
  18. for(int i=0;i<KD;++i)
  19. minn[i]=maxx[i]=p[i];
  20. }
  21. }T[N];
  22. bool operator < (const Node &a,const Node &b){return a.p[dn] < b.p[dn];}
  23. void pushup(const int &rt)
  24. {
  25. T[rt].sumv=T[rt].w;
  26. for(int i=0;i<2;++i)
  27. if(T[rt].ch[i])
  28. {
  29. T[rt].sumv+=T[T[rt].ch[i]].sumv;
  30. for(int j=0;j<KD;++j)
  31. {
  32. T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]);
  33. T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]);
  34. }
  35. }
  36. }
  37. int buildtree(int l=1,int r=n,int d=0)
  38. {
  39. dn=d;
  40. int m=(l+r>>1);
  41. nth_element(T+l,T+m,T+r+1);
  42. T[m].Init();
  43. if(l!=m) T[m].ch[0]=buildtree(l,m-1,(d+1)%KD);
  44. if(m!=r) T[m].ch[1]=buildtree(m+1,r,(d+1)%KD);
  45. pushup(m);
  46. return m;
  47. }
  48. bool Inside(const int &o)
  49. {
  50. for(int i=0;i<KD;++i)
  51. if(qp[0][i] > T[o].p[i] || T[o].p[i] > qp[1][i])
  52. return 0;
  53. return 1;
  54. }
  55. bool AllInside(const int &o)
  56. {
  57. for(int i=0;i<KD;++i)
  58. if(qp[0][i] > T[o].minn[i] || T[o].maxx[i] > qp[1][i])
  59. return 0;
  60. return 1;
  61. }
  62. bool Cross(const int &o)
  63. {
  64. for(int i=0;i<KD;++i)
  65. if(qp[0][i] > T[o].maxx[i] || T[o].minn[i] > qp[1][i])
  66. return 0;
  67. return 1;
  68. }
  69. int ans;
  70. void Query(int rt=root)
  71. {
  72. if(Inside(rt)) ans+=T[rt].w;
  73. for(int i=0;i<2;++i)
  74. if(T[rt].ch[i] && Cross(T[rt].ch[i]))
  75. {
  76. if(AllInside(T[rt].ch[i]))
  77. ans+=T[T[rt].ch[i]].sumv;
  78. else if(T[T[rt].ch[i]].sumv)
  79. Query(T[rt].ch[i]);
  80. }
  81. }
  82.  
  83. int q;
  84. string s[Q],t;
  85. int ch[N][26];
  86. int sz,Ls[4][N],Rs[4][N];
  87. int num[4][Q];
  88. void Insert(int op,int id,string s)
  89. {
  90. int U=0,len=s.length();
  91. for(int i=0;i<len;++i)
  92. {
  93. int V=s[i]-'a';
  94. if(!ch[U][V]) ch[U][V]=++sz;
  95. U=ch[U][V];
  96. }
  97. num[op][id]=U;
  98. }
  99. string as[Q],bs[Q],cs[Q],ds[Q];
  100. int tot;
  101. void dfs(int op,int U){
  102. Ls[op][U]=++tot;
  103. for(int i=0;i<26;++i){
  104. if(ch[U][i]){
  105. dfs(op,ch[U][i]);
  106. }
  107. }
  108. Rs[op][U]=tot;
  109. }
  110. int main()
  111. {
  112. // freopen("i.in","r",stdin);
  113. // freopen("i.out","w",stdout);
  114. int opt,zu;
  115. scanf("%d",&zu);
  116. for(;zu;--zu){
  117. n=0;
  118. memset(ch,0,sizeof(ch));
  119. sz=0;
  120. scanf("%d",&q);
  121. for(int i=1;i<=q;++i){
  122. scanf("%d",&opt);
  123. if(opt==1){
  124. cin>>s[i];
  125. ++n;
  126. }
  127. else{
  128. cin>>as[i]>>bs[i]>>cs[i]>>ds[i];
  129. }
  130. }
  131. for(int j=1;j<=q;++j)
  132. if(s[j]!=""){
  133. int slen=s[j].length();
  134. t=s[j].substr(0,slen>>1);
  135. Insert(0,j,t);
  136. }
  137. else{
  138. int alen=as[j].length();
  139. Insert(0,j,as[j]);
  140. }
  141. tot=0;
  142. dfs(0,0);
  143. memset(ch,0,sizeof(ch));
  144. sz=0;
  145. for(int j=1;j<=q;++j)
  146. if(s[j]!=""){
  147. int slen=s[j].length();
  148. t=s[j].substr(0,slen>>1);
  149. reverse(t.begin(),t.end());
  150. Insert(1,j,t);
  151. }
  152. else{
  153. int blen=bs[j].length();
  154. reverse(bs[j].begin(),bs[j].end());
  155. Insert(1,j,bs[j]);
  156. }
  157. tot=0;
  158. dfs(1,0);
  159. memset(ch,0,sizeof(ch));
  160. sz=0;
  161. for(int j=1;j<=q;++j)
  162. if(s[j]!=""){
  163. int slen=s[j].length();
  164. t=s[j].substr(slen>>1,slen>>1);
  165. Insert(2,j,t);
  166. }
  167. else{
  168. int clen=cs[j].length();
  169. Insert(2,j,cs[j]);
  170. }
  171. tot=0;
  172. dfs(2,0);
  173. memset(ch,0,sizeof(ch));
  174. sz=0;
  175. for(int j=1;j<=q;++j)
  176. if(s[j]!=""){
  177. int slen=s[j].length();
  178. t=s[j].substr(slen>>1,slen>>1);
  179. reverse(t.begin(),t.end());
  180. Insert(3,j,t);
  181. }
  182. else{
  183. int dlen=ds[j].length();
  184. reverse(ds[j].begin(),ds[j].end());
  185. Insert(3,j,ds[j]);
  186. }
  187. tot=0;
  188. dfs(3,0);
  189. int cnt=0;
  190. for(int i=1;i<=q;++i)if(s[i]!=""){
  191. ++cnt;
  192. T[cnt].p[0]=Ls[0][num[0][i]];
  193. T[cnt].p[1]=Ls[1][num[1][i]];
  194. T[cnt].p[2]=Ls[2][num[2][i]];
  195. T[cnt].p[3]=Ls[3][num[3][i]];
  196. T[cnt].p[4]=i;
  197. T[cnt].p[5]=s[i].length();
  198. T[cnt].w=1;
  199. }
  200. root=(1+n>>1);
  201. buildtree();
  202. for(int i=1;i<=q;++i){
  203. if(as[i]!=""){
  204. ans=0;
  205. qp[0][0]=Ls[0][num[0][i]]; qp[1][0]=Rs[0][num[0][i]];
  206. qp[0][1]=Ls[1][num[1][i]]; qp[1][1]=Rs[1][num[1][i]];
  207. qp[0][2]=Ls[2][num[2][i]]; qp[1][2]=Rs[2][num[2][i]];
  208. qp[0][3]=Ls[3][num[3][i]]; qp[1][3]=Rs[3][num[3][i]];
  209. qp[0][4]=1; qp[1][4]=i;
  210. qp[0][5]=max(as[i].length()+bs[i].length(),cs[i].length()+ds[i].length())*2;
  211. qp[1][5]=2147483647;
  212. Query();
  213. printf("%d\n",ans);
  214. }
  215. }
  216. for(int i=1;i<=q;++i){
  217. s[i].clear();
  218. as[i].clear();
  219. bs[i].clear();
  220. cs[i].clear();
  221. ds[i].clear();
  222. }
  223. }
  224. return 0;
  225. }

【Trie】【kd-tree】计蒜客17122 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 I. Barty's Computer的更多相关文章

  1. 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 M. Frequent Subsets Problem【状态压缩】

    2017 ACM-ICPC 亚洲区(南宁赛区)网络赛  M. Frequent Subsets Problem 题意:给定N和α还有M个U={1,2,3,...N}的子集,求子集X个数,X满足:X是U ...

  2. 【计算几何】【圆反演】计蒜客17314 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 G. Finding the Radius for an Inserted Circle

    题意:给你三个半径相同的圆,它们切在一起,然后让你往缝里一个一个地塞圆,问你塞到第k个的半径是多少. 就把上面那两个圆的切点当成反演中心,然后会反演成这个样子,两个平行直线和一个圆. 然后就是往那个圆 ...

  3. 【分块】计蒜客17120 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor

    题意:给一棵树,每个点有权值.q次询问a,b,k,问你从a点到b点,每次跳距离k,权值的异或和? 预处理每个点往其根节点的路径上隔1~sqrt(n)的距离的异或和,然后把询问拆成a->lca(a ...

  4. 【推导】计蒜客17119 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F. Trig Function

    题意:给你n,m,让你求cos(nx)的展开式的(cos(x))^m项的系数. 更一般的式子是这样的:. 队友的代码: #include<cstdio> #include<algor ...

  5. 【找规律】计蒜客17118 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 E. Maximum Flow

    题意:一张有n个点的图,结点被编号为0~n-1,i往所有编号比它大的点j连边,权值为i xor j.给你n,问你最大流. 打个表,别忘了把相邻两项的差打出来,你会发现神奇的规律……你会发现每个答案都是 ...

  6. 【推导】计蒜客17116 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 C. Sum

    题意:S(x)被定义为x的十进制表示下的数位之和.给你x,让你找一个正整数k,使得S(kx)能被233整除.k不超过2千位. 由于x不超过1000000,不论x是多少,10000000重复233次一定 ...

  7. 【二项式定理】【推导】计蒜客17115 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B. Coin

    题意:投一枚硬币向上的概率是q/p.问你投K枚硬币,向上的枚数为偶数枚的概率是? 要求的即为. 这个东西是个二项展开式的偶数项系数和,来,我们复习一下高中数学,设f(x)=(ax+b)^n,则其偶数项 ...

  8. 计蒜客 31453 - Hard to prepare - [递归][2018ICPC徐州网络预赛A题]

    题目链接:https://nanti.jisuanke.com/t/31453 After Incident, a feast is usually held in Hakurei Shrine. T ...

  9. 计蒜客 31452 - Supreme Number - [简单数学][2018ICPC沈阳网络预赛K题]

    题目链接:https://nanti.jisuanke.com/t/31452 A prime number (or a prime) is a natural number greater than ...

随机推荐

  1. MSSQL DBcheck

    --1.创建数据库. --create database MyDatabase; --删除数据库 --drop database MyDatabase; ----------------------- ...

  2. java===java基础学习(14)---封装

    package dog; public class Demo4 { public static void main(String []args) { Worker w1= new Worker(&qu ...

  3. win7旗舰版64位缺失tbb.dll文件

    win7旗舰版64位缺失tbb.dll文件 https://zhidao.baidu.com/question/688589990330312804.html 到好的电脑中复制一个,黏贴到下同的路径下 ...

  4. auth src

    https://github.com/jbeverly/pam_ssh_agent_auth https://github.com/aur-archive/pam-face-authenticatio ...

  5. 【模板】BZOJ 1692:队列变换—后缀数组 Suffix Array

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1692 题意: 给出一个长度为N的字符串,每次可以从串头或串尾取一个字符,添加到新串中,使新串 ...

  6. sql server 学习笔记

    1. 修改student表中sdept字段改为varchar类型,长度为30,并且不为空 ) not null 2. 删除student表中的address列 alter table student ...

  7. DevExpress.XtraTreeList 小结

    搞了半天才绑定好,没有弄清楚父子之间的关系 <dx:ASPxTreeList ID="ASPxTreeList1" runat="server" Auto ...

  8. JS如何获取Input的name或者ID?

    <input name="music" type="image" id="music" onclick="loadmusic ...

  9. NOI openjudge 1792.迷宫

    一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n * n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行.同时当Extense处在某个格点时,他只 ...

  10. 几个例子理解对称加密与非对称加密、公钥与私钥、签名与验签、数字证书、HTTPS加密方式

    # 原创,转载请留言联系 为什么会出现这么多加密啊,公钥私钥啊,签名啊这些东西呢?说到底还是保证双方通信的安全性与完整性.例如小明发一封表白邮件给小红,他总不希望给别人看见吧.而各种各样的技术就是为了 ...