题意: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是开不下的,只能开一个,重复利用空间……

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
using namespace std;
#define N 2000005
#define Q 30005
#define KD 6
int dn,n,root,qp[2][KD];
struct Node
{
int ch[2],w,minn[KD],maxx[KD],p[KD],sumv;
void Init()
{
sumv=w;
ch[0]=ch[1]=0;
for(int i=0;i<KD;++i)
minn[i]=maxx[i]=p[i];
}
}T[N];
bool operator < (const Node &a,const Node &b){return a.p[dn] < b.p[dn];}
void pushup(const int &rt)
{
T[rt].sumv=T[rt].w;
for(int i=0;i<2;++i)
if(T[rt].ch[i])
{
T[rt].sumv+=T[T[rt].ch[i]].sumv;
for(int j=0;j<KD;++j)
{
T[rt].minn[j]=min(T[rt].minn[j],T[T[rt].ch[i]].minn[j]);
T[rt].maxx[j]=max(T[rt].maxx[j],T[T[rt].ch[i]].maxx[j]);
}
}
}
int buildtree(int l=1,int r=n,int d=0)
{
dn=d;
int m=(l+r>>1);
nth_element(T+l,T+m,T+r+1);
T[m].Init();
if(l!=m) T[m].ch[0]=buildtree(l,m-1,(d+1)%KD);
if(m!=r) T[m].ch[1]=buildtree(m+1,r,(d+1)%KD);
pushup(m);
return m;
}
bool Inside(const int &o)
{
for(int i=0;i<KD;++i)
if(qp[0][i] > T[o].p[i] || T[o].p[i] > qp[1][i])
return 0;
return 1;
}
bool AllInside(const int &o)
{
for(int i=0;i<KD;++i)
if(qp[0][i] > T[o].minn[i] || T[o].maxx[i] > qp[1][i])
return 0;
return 1;
}
bool Cross(const int &o)
{
for(int i=0;i<KD;++i)
if(qp[0][i] > T[o].maxx[i] || T[o].minn[i] > qp[1][i])
return 0;
return 1;
}
int ans;
void Query(int rt=root)
{
if(Inside(rt)) ans+=T[rt].w;
for(int i=0;i<2;++i)
if(T[rt].ch[i] && Cross(T[rt].ch[i]))
{
if(AllInside(T[rt].ch[i]))
ans+=T[T[rt].ch[i]].sumv;
else if(T[T[rt].ch[i]].sumv)
Query(T[rt].ch[i]);
}
} int q;
string s[Q],t;
int ch[N][26];
int sz,Ls[4][N],Rs[4][N];
int num[4][Q];
void Insert(int op,int id,string s)
{
int U=0,len=s.length();
for(int i=0;i<len;++i)
{
int V=s[i]-'a';
if(!ch[U][V]) ch[U][V]=++sz;
U=ch[U][V];
}
num[op][id]=U;
}
string as[Q],bs[Q],cs[Q],ds[Q];
int tot;
void dfs(int op,int U){
Ls[op][U]=++tot;
for(int i=0;i<26;++i){
if(ch[U][i]){
dfs(op,ch[U][i]);
}
}
Rs[op][U]=tot;
}
int main()
{
// freopen("i.in","r",stdin);
// freopen("i.out","w",stdout);
int opt,zu;
scanf("%d",&zu);
for(;zu;--zu){
n=0;
memset(ch,0,sizeof(ch));
sz=0;
scanf("%d",&q);
for(int i=1;i<=q;++i){
scanf("%d",&opt);
if(opt==1){
cin>>s[i];
++n;
}
else{
cin>>as[i]>>bs[i]>>cs[i]>>ds[i];
}
}
for(int j=1;j<=q;++j)
if(s[j]!=""){
int slen=s[j].length();
t=s[j].substr(0,slen>>1);
Insert(0,j,t);
}
else{
int alen=as[j].length();
Insert(0,j,as[j]);
}
tot=0;
dfs(0,0);
memset(ch,0,sizeof(ch));
sz=0;
for(int j=1;j<=q;++j)
if(s[j]!=""){
int slen=s[j].length();
t=s[j].substr(0,slen>>1);
reverse(t.begin(),t.end());
Insert(1,j,t);
}
else{
int blen=bs[j].length();
reverse(bs[j].begin(),bs[j].end());
Insert(1,j,bs[j]);
}
tot=0;
dfs(1,0);
memset(ch,0,sizeof(ch));
sz=0;
for(int j=1;j<=q;++j)
if(s[j]!=""){
int slen=s[j].length();
t=s[j].substr(slen>>1,slen>>1);
Insert(2,j,t);
}
else{
int clen=cs[j].length();
Insert(2,j,cs[j]);
}
tot=0;
dfs(2,0);
memset(ch,0,sizeof(ch));
sz=0;
for(int j=1;j<=q;++j)
if(s[j]!=""){
int slen=s[j].length();
t=s[j].substr(slen>>1,slen>>1);
reverse(t.begin(),t.end());
Insert(3,j,t);
}
else{
int dlen=ds[j].length();
reverse(ds[j].begin(),ds[j].end());
Insert(3,j,ds[j]);
}
tot=0;
dfs(3,0);
int cnt=0;
for(int i=1;i<=q;++i)if(s[i]!=""){
++cnt;
T[cnt].p[0]=Ls[0][num[0][i]];
T[cnt].p[1]=Ls[1][num[1][i]];
T[cnt].p[2]=Ls[2][num[2][i]];
T[cnt].p[3]=Ls[3][num[3][i]];
T[cnt].p[4]=i;
T[cnt].p[5]=s[i].length();
T[cnt].w=1;
}
root=(1+n>>1);
buildtree();
for(int i=1;i<=q;++i){
if(as[i]!=""){
ans=0;
qp[0][0]=Ls[0][num[0][i]]; qp[1][0]=Rs[0][num[0][i]];
qp[0][1]=Ls[1][num[1][i]]; qp[1][1]=Rs[1][num[1][i]];
qp[0][2]=Ls[2][num[2][i]]; qp[1][2]=Rs[2][num[2][i]];
qp[0][3]=Ls[3][num[3][i]]; qp[1][3]=Rs[3][num[3][i]];
qp[0][4]=1; qp[1][4]=i;
qp[0][5]=max(as[i].length()+bs[i].length(),cs[i].length()+ds[i].length())*2;
qp[1][5]=2147483647;
Query();
printf("%d\n",ans);
}
}
for(int i=1;i<=q;++i){
s[i].clear();
as[i].clear();
bs[i].clear();
cs[i].clear();
ds[i].clear();
}
}
return 0;
}

【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. vs调试 配置IISExpress允许局域网内部访问

    内网可访问后,本机不能使用localhost   1.找到IISExpress的配置文件,位于 <文档>/IISExpress/config文件夹下,打开applicationhost.c ...

  2. js_开发小技巧记录(一)

    (一) 生成从minNum到maxNum的随机数 <!DOCTYPE html> <html> <head> <meta charset="UTF- ...

  3. 常见网络命令之Ping命令

    前言:计算机网络老师要求我们自己总结一下常见的网络命,然后上课可以上去讲一下这些命令使用,像我这么听话的好学生,肯定是照老师要求,认真的总结了一下,总结的过程中,我发现网上已经有的资源讲的都不是很详细 ...

  4. 【快速玩转Source Filmmaker】用黑科技做出自己的OC和想要的模型

    [快速玩转Source Filmmaker]用黑科技做出自己的OC和想要的模型https://tieba.baidu.com/p/4154097168

  5. mac 使用清除废纸篓或彻底删除某文件 附加: smb afp ftp NAS 访问服务器相关

    mac 使用清除废纸篓或彻底删除某文件 附加: smb afp ftp NAS 访问服务器相关 mac 下删除文件方法: 1.使用 cleanmymac  使用 cleamymac 的清理  和 逐个 ...

  6. centos安装ss教程

    在CentOS 6.6上安装ShadowSocks服务端 1.查看系统[root@localhost ~]# cat /etc/issue CentOS release 6.6 (Final) [ro ...

  7. ios IAP 内购验证

    参考我之前的笔记 苹果内购笔记,在客户端向苹果购买成功之后,我们需要进行二次验证. 二次验证 IOS在沙箱环境下购买成功之后,向苹果进行二次验证,确认用户是否购买成功. 当应用向Apple服务器请求购 ...

  8. iframe的一些介绍

    iframe 元素会创建包含另外一个文档的内联框架(即行内框架) 提示:您可以把需要的文本放置在 <iframe> 和 </iframe> 之间,这样就可以应对无法理解 ifr ...

  9. 我的新博客地址http://xxxbw.github.io/

    最近在学github,在github搭了个博客,以后也会使用另外一个博客.有兴趣的小伙伴可以看看~ 地址:http://xxxbw.github.io/

  10. for in 对象时,属性为非负整数的情况

    在我做一个需求的时候 for in 一个对象,对象的属性都是数字 但是我想给这个对象加一个默认的属性跟值 原对象是{5446:"广州市"}.....类似于下去 然后我想给我页面展示 ...