【Trie】【kd-tree】计蒜客17122 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 I. Barty's Computer
题意: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的更多相关文章
- 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 ...
- 【计算几何】【圆反演】计蒜客17314 2017 ACM-ICPC 亚洲区(南宁赛区)网络赛 G. Finding the Radius for an Inserted Circle
题意:给你三个半径相同的圆,它们切在一起,然后让你往缝里一个一个地塞圆,问你塞到第k个的半径是多少. 就把上面那两个圆的切点当成反演中心,然后会反演成这个样子,两个平行直线和一个圆. 然后就是往那个圆 ...
- 【分块】计蒜客17120 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 G. Xor
题意:给一棵树,每个点有权值.q次询问a,b,k,问你从a点到b点,每次跳距离k,权值的异或和? 预处理每个点往其根节点的路径上隔1~sqrt(n)的距离的异或和,然后把询问拆成a->lca(a ...
- 【推导】计蒜客17119 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F. Trig Function
题意:给你n,m,让你求cos(nx)的展开式的(cos(x))^m项的系数. 更一般的式子是这样的:. 队友的代码: #include<cstdio> #include<algor ...
- 【找规律】计蒜客17118 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 E. Maximum Flow
题意:一张有n个点的图,结点被编号为0~n-1,i往所有编号比它大的点j连边,权值为i xor j.给你n,问你最大流. 打个表,别忘了把相邻两项的差打出来,你会发现神奇的规律……你会发现每个答案都是 ...
- 【推导】计蒜客17116 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 C. Sum
题意:S(x)被定义为x的十进制表示下的数位之和.给你x,让你找一个正整数k,使得S(kx)能被233整除.k不超过2千位. 由于x不超过1000000,不论x是多少,10000000重复233次一定 ...
- 【二项式定理】【推导】计蒜客17115 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 B. Coin
题意:投一枚硬币向上的概率是q/p.问你投K枚硬币,向上的枚数为偶数枚的概率是? 要求的即为. 这个东西是个二项展开式的偶数项系数和,来,我们复习一下高中数学,设f(x)=(ax+b)^n,则其偶数项 ...
- 计蒜客 31453 - Hard to prepare - [递归][2018ICPC徐州网络预赛A题]
题目链接:https://nanti.jisuanke.com/t/31453 After Incident, a feast is usually held in Hakurei Shrine. T ...
- 计蒜客 31452 - Supreme Number - [简单数学][2018ICPC沈阳网络预赛K题]
题目链接:https://nanti.jisuanke.com/t/31452 A prime number (or a prime) is a natural number greater than ...
随机推荐
- MSSQL DBcheck
--1.创建数据库. --create database MyDatabase; --删除数据库 --drop database MyDatabase; ----------------------- ...
- java===java基础学习(14)---封装
package dog; public class Demo4 { public static void main(String []args) { Worker w1= new Worker(&qu ...
- win7旗舰版64位缺失tbb.dll文件
win7旗舰版64位缺失tbb.dll文件 https://zhidao.baidu.com/question/688589990330312804.html 到好的电脑中复制一个,黏贴到下同的路径下 ...
- auth src
https://github.com/jbeverly/pam_ssh_agent_auth https://github.com/aur-archive/pam-face-authenticatio ...
- 【模板】BZOJ 1692:队列变换—后缀数组 Suffix Array
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1692 题意: 给出一个长度为N的字符串,每次可以从串头或串尾取一个字符,添加到新串中,使新串 ...
- sql server 学习笔记
1. 修改student表中sdept字段改为varchar类型,长度为30,并且不为空 ) not null 2. 删除student表中的address列 alter table student ...
- DevExpress.XtraTreeList 小结
搞了半天才绑定好,没有弄清楚父子之间的关系 <dx:ASPxTreeList ID="ASPxTreeList1" runat="server" Auto ...
- JS如何获取Input的name或者ID?
<input name="music" type="image" id="music" onclick="loadmusic ...
- NOI openjudge 1792.迷宫
一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n * n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行.同时当Extense处在某个格点时,他只 ...
- 几个例子理解对称加密与非对称加密、公钥与私钥、签名与验签、数字证书、HTTPS加密方式
# 原创,转载请留言联系 为什么会出现这么多加密啊,公钥私钥啊,签名啊这些东西呢?说到底还是保证双方通信的安全性与完整性.例如小明发一封表白邮件给小红,他总不希望给别人看见吧.而各种各样的技术就是为了 ...