正题

题目链接: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(nlog⁡n)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,树状数组】相关推荐

  1. 洛谷 P2336 [SCOI2012]喵星球上的点名 解题报告

    P2336 [SCOI2012]喵星球上的点名 题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 \(N\) 个喵星人,每个喵星人的 ...

  2. 洛谷 P2336 [SCOI2012]喵星球上的点名

    题目描述 a180285 幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有 N 个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M 个串来点名,每 ...

  3. 洛谷2336 BZOJ2754 SCOI2012 喵星球上的点名 SA 莫队 二分

    题目链接 题意: 有nnn个人,每个人有两个串,一个表示姓,一个表示名,这里用数字表示字符.有mmm次询问,对于每次询问,你要回答有多少个人的姓或者名至少有一个是给出的串的子串.最后再对于这nnn个人 ...

  4. 【BZOJ2754】[SCOI2012]喵星球上的点名

    [BZOJ2754][SCOI2012]喵星球上的点名 题面 bzoj 洛谷 题解 这题有各种神仙做法啊,什么暴力\(AC\)自动机.\(SAM\)等等五花八门 我这个蒟蒻在这里提供一种复杂度正确且常 ...

  5. BZOJ 2754: [SCOI2012]喵星球上的点名

    二次联通门 : BZOJ 2754: [SCOI2012]喵星球上的点名 /*BZOJ 2754: [SCOI2012]喵星球上的点名此题有N种做法...见到众dalao用各种奇怪的姿势AC此题..具 ...

  6. SCOI2012 喵星球上的点名 BZOJ 2754

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 2246 Solved: 975 Description ...

  7. 2754. [SCOI2012]喵星球上的点名【后缀数组】

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串 ...

  8. 【刷题】BZOJ 2754 [SCOI2012]喵星球上的点名

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点 ...

  9. [SCOI2012]喵星球上的点名

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点 ...

  10. BZOJ2754: [SCOI2012]喵星球上的点名(AC自动机/后缀自动机)

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣.   假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串 ...

最新文章

  1. input[type=file]属性
  2. c++中有表示正无穷的数吗_阅读:贯穿编程人生CSAPP[2]信息表示
  3. Oracle查看死锁 .
  4. OCJP认证考试复习课-张晨光-专题视频课程
  5. 【智能AI】准确率97%的开源肺炎检测模型
  6. Java二进制小数表示_《Java编程的逻辑》笔记9--小数的二进制表示
  7. 【LA3487】最小割-经典模型 两种方法
  8. 第9章 项目人力资源管理
  9. 伪装Apache版本防止入侵Web服务器
  10. ubuntu 13 sogou input method install
  11. Nero刻录软件超级实用技巧大搜罗
  12. 聊聊微信内页面发Ajax请求会重复请求的问题
  13. 400家门店直接“云”上办公 JASONWOOD 是如何做到的?
  14. 我的河海大学计算机考研经验之谈
  15. openlayers3 ol3热力图 json
  16. 基于 python 的语音识别 API 调用
  17. IDEA2020安装教程
  18. Java接口和包(超详细)
  19. Lyndon的量化修炼之路——均线差与MACD联动策略(一)
  20. php5217 0day,知道创宇:最新版DEDECMS存SQL注入0day漏洞

热门文章

  1. pythonlive2d_Unity-Live2D资源载入
  2. 浮点数赋值给整数_初学者专题:变量和赋值
  3. php吞了throw错误,PHP 异常与错误处理
  4. tcl mysql_MySQL·TCL语言
  5. c语言求平衡因子,平衡二叉树(AVL树)的基本操作
  6. 机器人J中WPR_优傲:协作机器人的未来在哪里?
  7. pandas用均值填充nan_Pandas学习笔记(三)
  8. python字符串截取方法_如何使用python语言中的字符串方法截取字符串
  9. 7-7 有重复元素的全排列 (10 分)(set容器做法思路加详解)
  10. [JavaWeb-Bootstrap]CSS样式和JS插件