题目链接:喵星球上的点名

  首先可以发现姓和名两个串就是逗你玩的。在两个串中间插入一个\(10001\),当成一个串做就可以了。

  于是我们的问题转化为了:

  有\(n\)个串\(A_1,A_2,\dots,A_n\)和\(m\)个串\(B_1,B_2,\dots,B_m\),要对于每个\(B_i\)求出它被多少个\(A\)串包含,并要对每个\(A_i\)求出它包含了多少个\(B\)串。

  我们先把所有串丢到一个\(AC\)自动机里面,然后构出\(fail\)树。我们知道,如果\(S\)串包含了\(A\)串,那么在\(fail\)树上\(A\)串的结尾节点的子树里就会有\(S\)串的节点。所以构出\(dfs\)序之后,要求每个\(B_i\)求出它被多少个\(A\)串包含,就相当于询问区间不同的颜色数。做法同HH的项链

  第二问就是相当于每次给区间内所有元素加\(1\),但是相同的元素只加一次。记位置\(i\)的元素上一次出现的位置为\(pre_i\),那么每次操作\((l,r)\)就相当于给其中满足\(pre_i<l \le i \le r\)的\(i\)位置的元素加\(1\)。我们把所有二元组\(pre_i,i\)和所有询问\(l,r\)都按前一个数为第一关键字,后一个数为第二关键字排序,然后一起从后往前扫。对于每个二元组\(pre_i,i\),找出所有的满足\(pre_i<l\)的\(l,r\),给\(l,r\)区间加\(1\),然后位置\(i\)上的值就是\(i\)位置的元素被统计的次数。用一个树状数组维护即可。

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 300010
#define pb push_back using namespace std;
typedef long long llg; struct data{
int l,r,b;
bool operator < (const data &h)const{return l<h.l;}
}A[maxn],B[maxn];
int n,m,b[maxn],lb,tt,val[maxn],pr[maxn];
int d[maxn],fr[maxn],fl[maxn],a[maxn],la,c[maxn];
int hd[maxn],nt[maxn],le[maxn],ri[maxn],ans[maxn];
map<short int,int>s[maxn];
map<short int,int>::iterator it;
vector<int> q[maxn]; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} bool cmpr(data x,data y){return x.r<y.r;}
int insert(int x){
int u=0;
for(int i=1;i<=lb;i++){
if(!s[u][b[i]]) s[u][b[i]]=++tt,val[tt]=b[i];
u=s[u][b[i]]; if(x) q[u].pb(x);
}
return u;
} void getfail(){
int ld=0,rd=0; d[rd++]=0;
while(ld!=rd){
int u=d[ld++],j,v;
if(u) nt[u]=hd[fl[u]],hd[fl[u]]=u;
for(it=s[u].begin();it!=s[u].end();it++){
j=fl[u]; d[rd++]=v=(*it).second;
while(!s[j][val[v]] && j) j=fl[j];
if(u!=j) fl[v]=s[j][val[v]];
}
}
} void dfs(int u){
le[u]=la+1;
for(int i=q[u].size()-1;i>=0;i--){
a[++la]=q[u][i]; A[la].r=la;
A[la].l=pr[a[la]]; pr[a[la]]=la;
}
for(int i=hd[u];i;i=nt[i]) dfs(i);
ri[u]=la;
} void add(int x,int y){while(x<=la) c[x]+=y,x+=x&(-x);}
int sum(int x){
int t=0;
while(x) t+=c[x],x-=x&(-x);
return t;
} int main(){
File("a");
n=getint(),m=getint();
for(int i=1,x;i<=n;i++){
lb=0; x=getint();
while(x--) b[++lb]=getint();
b[++lb]=10001; x=getint();
while(x--) b[++lb]=getint();
insert(i);
}
for(int i=1,x;i<=m;i++){
lb=0; x=getint();
while(x--) b[++lb]=getint();
fr[i]=insert(0);
}
getfail(); dfs(0);
for(int i=1;i<=m;i++)
B[i].l=le[fr[i]],B[i].r=ri[fr[i]],B[i].b=i;
sort(B+1,B+m+1,cmpr); int bl=1;
while(!B[bl].r) bl++;
for(int i=1;i<=la;i++) pr[a[i]]=0;
for(int i=1,now=0;i<=la;i++){
if(pr[a[i]]) add(pr[a[i]],-1);
now+=(!pr[a[i]]); add(i,1); pr[a[i]]=i;
while(B[bl].r==i) ans[B[bl].b]=now-sum(B[bl].l-1),bl++;
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]),ans[i]=0;
for(int i=1;i<=la;i++) c[i]=0;
sort(A+1,A+la+1); sort(B+1,B+m+1);
for(int i=la,j=m;i;){
if(A[i].l<B[j].l) add(B[j].l,1),add(B[j].r+1,-1),j--;
else ans[a[A[i].r]]+=sum(A[i].r),i--;
}
for(int i=1;i<=n;i++){
printf("%d",ans[i]);
if(i<n) putchar(' ');
}
return 0;
}

  

BZOJ 2754 【SCOI2012】 喵星球上的点名的更多相关文章

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

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 649  Solved: 305[Submit][Sta ...

  2. BZOJ 2754: [SCOI2012]喵星球上的点名 [后缀数组+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1906  Solved: 839[Submit][St ...

  3. BZOJ 2754: [SCOI2012]喵星球上的点名 [AC自动机+map+暴力]

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1902  Solved: 837[Submit][St ...

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

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

  5. bzoj 2754 [SCOI2012]喵星球上的点名(后缀数组)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2754 [题意] 每只喵有名姓,如果被老师点到名或姓的子串都要答道,但每只喵一次点名只答 ...

  6. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机、树状数组)

    吐槽: 为啥很多人用AC自动机暴力跳都过了?复杂度真的对么? 做法一: AC自动机+树状数组 姓名的问题,中间加个特殊字符连起来即可. 肯定是对点名串建AC自动机(map存儿子),然后第一问就相当于问 ...

  7. BZOJ 2754 [SCOI2012]喵星球上的点名 (AC自动机+map维护Trie树)

    题目大意:略 由于字符集大,要用map维护Trie树 并不能用AC自动机的Trie图优化,不然内存会炸 所以我用AC自动机暴跳fail水过的 显然根据喵星人建AC自动机是不行的,所以要根据问题建 然而 ...

  8. bzoj 2754: [SCOI2012]喵星球上的点名【AC自动机】

    洛谷90,最后一个点死活卡不过去(也可能是我写的有问题? 比较暴力的做法,把询问带着标号建立AC自动机,用map存儿子. 然后用名字串在自动机上跑,以为是名或姓的子串就行所以把名和姓中间加个特殊字符拼 ...

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

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

  10. BZOJ2754: [SCOI2012]喵星球上的点名

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 680  Solved: 314[Submit][Sta ...

随机推荐

  1. Django框架----权限管理(设计分析以及具体细节)

    说起权限我们大家都知道,不一样的角色会有不一样的权限.比如就像学生管理系统一样,管理员,老师,学生之间的权限都是不一样的,那么展示的页面也是不一样的.所以,我们现在来看看具体操作. 目标:生成一个独立 ...

  2. WTL CHyperLink类的使用(超链接)

    1.包含atlctrlx.h头文件: 2.声明一个CHyperLink类的变量: CHyperLink        m_linkIntro; 3.在OnInitDialog函数里: m_linkIn ...

  3. The Little Prince-11/27

    The Little Prince-11/27    The little boy gradually realized that it is tiresome for children to be ...

  4. JVM 一套卷,助你快速掌握优化法则

    一:虚拟机内存图解 JAVA 程序运行与虚拟机之上,运行时需要内存空间.虚拟机执行 JAVA 程序的过程中会把它管理的内存划分为不同的数据区域方便管理. 虚拟机管理内存数据区域划分如下图: 数据区域分 ...

  5. 【开源】EasyFlash 新年发布 V4.0 beta 版,完全重写(转)

    [开源]EasyFlash 新年发布 V4.0 beta 版,完全重写 EasyFlash V4.0 beta [开源]嵌入式闪存库 EasyFlash for STM32,支持Env和IAP

  6. django图书管理系统实例

    首页,其他页面全部继承首页的上半部分 点击发布图书页面 首页点击书名,跳转到图书信息界面,该界面可删除图书 项目结构 #views.py from django.shortcuts import re ...

  7. JavaScript之BOM对象

    JavaScript bom对象 BOM对象 window对象 所有浏览器都支持 window 对象.概念上讲.一个html文档对应一个window对象.功能上讲: 控制浏览器窗口的.使用上讲: wi ...

  8. 创建docker镜像的私有仓库

    CentOS Linux release 7.2.1511 Docker version 17.03.1-ce 安装registry镜像 同时安装一个比较小的镜像alpine待会作测试用: # doc ...

  9. mvc 文件下载

    public class DownLoadHelper { /// <summary> /// WriteFile实现下载--测试通过 /// </summary> /// & ...

  10. 牛客网数据库SQL实战(21-25)

    21.查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_no以及其对应的薪水涨幅growth,并按照growth进行升序CREATE TABLE `employees` (`emp_no` i ...