P2336-[SCOI2012]喵星球上的点名【SA,树状数组】
正题
题目链接:https://www.luogu.com.cn/problem/P2336
题目大意
nnn个名字(每个名字两个串),mmm次点名,如果一次点名里是一个名字两个串中的子串该人就要答到。
对于每次点名求多少个人答到,每个名字求答到多少次。
解题思路
先考虑第一问,我们将所有串串在一起(中间加大数)然后跑出SASASA和所有的LCPLCPLCP。
然后对于每个点名串起始位置kkk我们寻找一个区间[l,r][l,r][l,r]使得LCP(k,i)≥len(i∈[l,r])LCP(k,i)\geq len(i\in[l,r])LCP(k,i)≥len(i∈[l,r])
这个区间我们求出heightheightheight后用STSTST表+二分可以求出
这样如果任意一个名字串的在这个区间内就会被点到。因为有名有姓,我们把同一个名字的SASASA染成同一种颜色,这样问题就变为了在[l,r][l,r][l,r]这个区间内有多少种颜色
而第二问也变为了有多少个区间包含该种颜色,我们直接用树状数组做就好了。
时间复杂度O(nlogn)O(n\log n)O(nlogn)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define lowbit(x) (x&-x)
using namespace std;
const int N=5e5+10;
struct node{int l,r,id;
}q[N];
int n,m,num,Q,s[N];
int col[N],len[N],head[N];
int sa[N],c[N],x[N],y[N];
int rk[N],height[N];
int st[N][20],lg[N];
int pre[N],last[N],qq[N];
int ans1[N],ans2[N];
struct Tree_Array{int t[N];void Change(int x,int val){if(!x) return;while(x<=n){t[x]+=val;x+=lowbit(x);}return;}int Ask(int x){int ans=0;while(x){ans+=t[x];x-=lowbit(x);}return ans;}
}T1,T2;
void Init(){scanf("%d%d",&num,&Q);m=1e4;for(int i=1;i<=num;i++){for(int j=0;j<2;j++){int x,c;scanf("%d",&x);while(x--){scanf("%d",&c);s[++n]=c;col[n]=i;}s[++n]=++m;}}for(int i=1;i<=Q;i++){int x;head[n+1]=i;scanf("%d",&len[i]);for(int j=1;j<=len[i];j++){scanf("%d",&x);s[++n]=x;col[n]=-i;}s[++n]=++m;}
}
void Qsort(){for(int i=1;i<=m;i++)c[i]=0;for(int i=1;i<=n;i++)c[x[i]]++;for(int i=1;i<=m;i++)c[i]+=c[i-1];for(int i=n;i>=1;i--)sa[c[x[y[i]]]--]=y[i],y[i]=0;return;
}
void Get_SA(){for(int i=1;i<=n;i++)x[i]=s[i],y[i]=i;Qsort();for(int w=1;w<=n;w<<=1){int p=0;for(int i=n-w+1;i<=n;i++) y[++p]=i;for(int i=1;i<=n;i++)if(sa[i]>w) y[++p]=sa[i]-w;Qsort();swap(x,y);x[sa[1]]=p=1;for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+w]==y[sa[i-1]+w])?p:++p;if(p==n) break;m=p;}return;
}
void Get_Height(){int k=0;for(int i=1;i<=n;i++)rk[sa[i]]=i;for(int i=1;i<=n;i++){//if(rk[i]==1) continue;if(k) k--;int j=sa[rk[i]-1];while(i+k<=n&&j+k<=n&&s[i+k]==s[j+k]) k++;height[rk[i]]=k;}return;
}
void Get_ST(){lg[0]=-1;for(int i=1;i<=n;i++)st[i][0]=height[i],lg[i]=lg[i>>1]+1;for(int j=1;j<19;j++)for(int i=1;i+(1<<j-1)<=n;i++)st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);return;
}
int LCP(int l,int r){if(l==r) return 1e9+7;if(l>r) swap(l,r);l++;int z=lg[r-l+1];return min(st[l][z],st[r+1-(1<<z)][z]);
}
bool cmp(node x,node y)
{return x.r<y.r;}
void Get_Pre(){for(int i=1;i<=n;i++){if(col[sa[i]]>0){pre[i]=last[col[sa[i]]];last[col[sa[i]]]=i;}if(head[i]){int l=1,r=rk[i];while(l<=r){int mid=(l+r)>>1;if(LCP(mid,rk[i])>=len[head[i]]) r=mid-1;else l=mid+1;}q[head[i]].l=l;l=rk[i];r=n;while(l<=r){int mid=(l+r)>>1;if(LCP(rk[i],mid)>=len[head[i]]) l=mid+1;else r=mid-1;}q[head[i]].r=r;q[head[i]].id=head[i];qq[q[head[i]].l]++;}}sort(q+1,q+1+Q,cmp);
}
void Get_Ans(){int h=1,z=1;for(int i=1;i<=n;i++){T2.Change(i,qq[i]);if(col[sa[i]]>0){T1.Change(pre[i],-1);T1.Change(i,1);ans2[col[sa[i]]]+=T2.Ask(i)-T2.Ask(pre[i]);}while(h<=Q&&q[h].r<=i){ans1[q[h].id]+=T1.Ask(q[h].r)-T1.Ask(q[h].l-1);T2.Change(q[h].l,-1);h++;}}return;
}
int main()
{Init();Get_SA();Get_Height();Get_ST();Get_Pre();Get_Ans();for(int i=1;i<=Q;i++)printf("%d\n",ans1[i]);for(int i=1;i<=num;i++)printf("%d ",ans2[i]);
}
P2336-[SCOI2012]喵星球上的点名【SA,树状数组】相关推荐
- 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告
P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...
- 洛谷 P2336 [SCOI2012]喵星球上的点名
题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 N 个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M 个串来点名,每 ...
- 洛谷2336 BZOJ2754 SCOI2012 喵星球上的点名 SA 莫队 二分
题目链接 题意: 有nnn个人,每个人有两个串,一个表示姓,一个表示名,这里用数字表示字符.有mmm次询问,对于每次询问,你要回答有多少个人的姓或者名至少有一个是给出的串的子串.最后再对于这nnn个人 ...
- 【BZOJ2754】[SCOI2012]喵星球上的点名
[BZOJ2754][SCOI2012]喵星球上的点名 题面 bzoj 洛谷 题解 这题有各种神仙做法啊,什么暴力\(AC\)自动机.\(SAM\)等等五花八门 我这个蒟蒻在这里提供一种复杂度正确且常 ...
- BZOJ 2754: [SCOI2012]喵星球上的点名
二次联通门 : BZOJ 2754: [SCOI2012]喵星球上的点名 /*BZOJ 2754: [SCOI2012]喵星球上的点名此题有N种做法...见到众dalao用各种奇怪的姿势AC此题..具 ...
- SCOI2012 喵星球上的点名 BZOJ 2754
2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 2246 Solved: 975 Description ...
- 2754. [SCOI2012]喵星球上的点名【后缀数组】
Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串 ...
- 【刷题】BZOJ 2754 [SCOI2012]喵星球上的点名
Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点 ...
- [SCOI2012]喵星球上的点名
Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点 ...
- BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机/后缀自动机)
Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串 ...
最新文章
- input[type=file]属性
- c++中有表示正无穷的数吗_阅读:贯穿编程人生CSAPP[2]信息表示
- Oracle查看死锁 .
- OCJP认证考试复习课-张晨光-专题视频课程
- 【智能AI】准确率97%的开源肺炎检测模型
- Java二进制小数表示_《Java编程的逻辑》笔记9--小数的二进制表示
- 【LA3487】最小割-经典模型 两种方法
- 第9章 项目人力资源管理
- 伪装Apache版本防止入侵Web服务器
- ubuntu 13 sogou input method install
- Nero刻录软件超级实用技巧大搜罗
- 聊聊微信内页面发Ajax请求会重复请求的问题
- 400家门店直接“云”上办公 JASONWOOD 是如何做到的?
- 我的河海大学计算机考研经验之谈
- openlayers3 ol3热力图 json
- 基于 python 的语音识别 API 调用
- IDEA2020安装教程
- Java接口和包(超详细)
- Lyndon的量化修炼之路——均线差与MACD联动策略(一)
- php5217 0day,知道创宇:最新版DEDECMS存SQL注入0day漏洞
热门文章
- pythonlive2d_Unity-Live2D资源载入
- 浮点数赋值给整数_初学者专题:变量和赋值
- php吞了throw错误,PHP 异常与错误处理
- tcl mysql_MySQL·TCL语言
- c语言求平衡因子,平衡二叉树(AVL树)的基本操作
- 机器人J中WPR_优傲:协作机器人的未来在哪里?
- pandas用均值填充nan_Pandas学习笔记(三)
- python字符串截取方法_如何使用python语言中的字符串方法截取字符串
- 7-7 有重复元素的全排列 (10 分)(set容器做法思路加详解)
- [JavaWeb-Bootstrap]CSS样式和JS插件