记录编号 216610 评测结果 AAAAAAAAAA
题目名称 [SCOI 2012] 喵星球上的点名 最终得分 100
用户昵称 Gravatar0 是否通过 通过
代码语言 C++ 运行时间 4.609 s
提交时间 2015-12-30 08:19:50 内存使用 86.21 MiB
显示代码纯文本
#include<cstdio>
#include<iostream>

#define maxn 200010
#define lson tr[rt].l
#define rson tr[rt].r

using namespace std;

int n,m,s[maxn],st[maxn],sa[maxn],rank[maxn],c[maxn],t[maxn],tt[maxn],len,num;
int las[maxn],bel[maxn],ans[maxn],rot[maxn],mark[maxn*30];

struct Tree{
	int l,r,w,ver;
}tr[maxn*30];

void getsa()
{
	int *x=t,*y=tt,n=len,m=10001;
	for(int i=1;i<=n;i++) c[x[i]=s[i]]++;
	for(int i=1;i<=m;i++) c[i]+=c[i-1];
	for(int i=1;i<=n;i++) sa[c[x[i]]--]=i;
	for(int k=1;k<=n;k<<=1){
		int p=0;
		for(int i=n-k+1;i<=n;i++) y[++p]=i;
		for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;
		for(int i=0;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=p;i>=1;i--) sa[c[x[y[i]]]--]=y[i];
		swap(x,y);
		p=1;x[sa[1]]=1;
		for(int i=2;i<=n;i++) 
			x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p;
		m=p;
		if(m>=n) break;
	}
	return;
}

inline void update(int rt){ tr[rt].w=tr[lson].w+tr[rson].w; }

void Modify(int pos,int val,int l,int r,int lrt,int &rt,int ver)
{
	if(tr[rt].ver!=ver){
		rt=++num;
		tr[rt]=tr[lrt];
		tr[rt].ver=ver;
	}
	if(l==r){
		tr[rt].w+=val;return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid){
		Modify(pos,val,l,mid,tr[lrt].l,lson,ver);
	}else{
		Modify(pos,val,mid+1,r,tr[lrt].r,rson,ver);
	}
	update(rt);
	return;
}

int Query(int al,int ar,int l,int r,int rt)
{
	if(tr[rt].w==0) return 0;
	if(al<=l&&r<=ar){
		mark[rt]++;
		return tr[rt].w;
	}
	int mid=(l+r)>>1;
	int ret=0;
	if(mid>=al){
		ret+=Query(al,ar,l,mid,lson);
	}
	if(mid<ar){
		ret+=Query(al,ar,mid+1,r,rson);
	}
	return ret;
}

inline bool cmp1(int l,int len)
{
	for(int i=1;i<=len;i++,l++){
		if(s[l]==st[i]) continue;
		if(s[l]<st[i]) return 1;
		return 0;
	}
	return 1;
}

inline bool cmp2(int l,int len)
{
	for(int i=1;i<=len;i++,l++){
		if(s[l]==st[i]) continue;
		if(s[l]<st[i]) return 0;
		return 1;
	}
	return 1;
}

int findr(int n)
{
	int l=1,r=len,ret=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(cmp1(sa[mid],n)){
			ret=mid;
			l=mid+1;
		}else{
			r=mid-1;
		}
	}
	return ret;
}

int findl(int n)
{
	int l=1,r=len,ret=len+1;
	while(l<=r){
		int mid=(l+r)>>1;
		if(cmp2(sa[mid],n)){
			ret=mid;
			r=mid-1;
		}else{
			l=mid+1;
		}
	}
	return ret;
}

void clearmark(int l,int r,int rt,int ver)
{
	if(tr[rt].ver!=ver||!tr[rt].w) return;
	if(l==r){
		ans[bel[sa[l]]]+=mark[rt];
		mark[rt]=0;
		return;
	}
	int mid=(l+r)>>1;
	mark[lson]+=mark[rt];
	mark[rson]+=mark[rt];
	clearmark(l,mid,lson,ver);
	clearmark(mid+1,r,rson,ver);
	mark[rt]=0;
	return;
}

int main()
{
	freopen("wtfname.in","r",stdin);
	freopen("wtfname.out","w",stdout);
	scanf("%d%d",&n,&m);len++;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=2;j++){
			int _n;scanf("%d",&_n);
			for(int k=1;k<=_n;len++,k++){
				scanf("%d",&s[len]);
				bel[len]=i;
			}
			bel[len]=i;
			s[len++]=10001;
		}
	}
	len--;
	getsa();
	for(int i=1;i<=len;i++){
		if(las[bel[sa[i]]]) Modify(las[bel[sa[i]]],-1,1,len,rot[i-1],rot[i],i);
		Modify(i,1,1,len,rot[i-1],rot[i],i);
		las[bel[sa[i]]]=i;
	}
	for(int i=1;i<=m;i++){
		int _n;
		scanf("%d",&_n);
		for(int i=1;i<=_n;i++) scanf("%d",&st[i]);
		int al=findl(_n),ar=findr(_n);
		if(al>ar){
			puts("0");continue;
		}
		printf("%d\n",Query(al,ar,1,len,rot[ar]));
	}
	for(int i=len;i>0;i--){
		clearmark(1,len,rot[i],i);
	}
	for(int i=1;i<n;i++) printf("%d ",ans[i]);
	printf("%d",ans[n]);
	getchar();getchar();
	return 0;
}