首页 > 其他分享 >P2336

P2336

时间:2024-10-02 18:44:58浏览次数:3  
标签:200005 int P2336 ans sa id

好久没发博客了(因为在家)
看到大家都是用后缀数组+莫队的,于是模仿题解搞了一搞

#include<bits/stdc++.h>
using namespace std;
int blk[200005];
struct ques {
	int l,r,id;
	inline friend bool operator <(ques A,ques B) {
		return blk[A.l]^blk[B.l]?blk[A.l]<blk[B.l]:(blk[A.l]&1?A.r<B.r:A.r>B.r);
	}
} q[100005];
int n,m,len,tot,a[200005],sa[200005],x,size,ans[100005],id[200005],cnt,t[50005],bkt[50005],lim=10000,L,R,ret;
class FileInputOutput {
	private:
#define S 1<<21
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
		char Fin[S],Fout[S],*A,*B;
		int Ftop,pt[15];
	public:
		inline void read(int &x) {
			x=0;
			char ch;
			while (!isdigit(ch=tc()));
			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
		}
		inline void write(int x,char ch) {
			if (!x) return (void)(pc('0'),pc(ch));
			register int ptop=0;
			while (x) pt[++ptop]=x%10,x/=10;
			while (ptop) pc(pt[ptop--]+48);
			pc(ch);
		}
		inline void Fend(void) {
			fwrite(Fout,1,Ftop,stdout);
		}
#undef S
#undef tc
#undef pc
} F;
class Suffix_Array {
	private:
		int rk[200005],t[200005],cnt[200005],size;
		inline void Radix_sort(int n) {
			register int i;
			for (i=0; i<=size; ++i) cnt[i]=0;
			for (i=1; i<=n; ++i) ++cnt[rk[i]];
			for (i=1; i<=size; ++i) cnt[i]+=cnt[i-1];
			for (i=n; i; --i) sa[cnt[rk[t[i]]]--]=t[i];
		}
	public:
		inline void build(int *a,int n) {
			register int i;
			size=a[n];
			for (i=1; i<=n; ++i) rk[i]=a[i],t[i]=i;
			Radix_sort(n);
			for (register int p=0,w=1; p<n; size=p,w<<=1) {
				for (p=0,i=n-w+1; i<=n; ++i) t[++p]=i;
				for (i=1; i<=n; ++i) if (sa[i]>w) t[++p]=sa[i]-w;
				Radix_sort(n);
				swap(rk,t);
				rk[sa[1]]=p=1;
				for (i=2; i<=n; ++i) rk[sa[i]]=(t[sa[i-1]]==t[sa[i]]&&t[sa[i-1]+w]==t[sa[i]+w])?p:++p;
			}
		}
} SA;
inline void add(int x,int cur) {
	if (++bkt[id[x]]==1) ++ret,t[id[x]]+=cnt-cur+1;
}
inline void del(int x,int cur) {
	if (--bkt[id[x]]==0) --ret,t[id[x]]-=cnt-cur+1;
}
int main() {

	register int i,j;
	for (F.read(n),F.read(m),i=1; i<=n; ++i) for (register int k=0; k<=1; ++k) {
			for (F.read(len),j=1; j<=len; ++j) F.read(a[++tot]),id[tot]=i;
			a[++tot]=++lim;
		}
	for (size=(int)sqrt(tot),i=1; i<=tot; ++i) blk[i]=(i-1)/size+1;
	for (SA.build(a,tot),i=1; i<=m; ++i) {
		for (F.read(len),L=j=1,R=tot; j<=len; ++j) {
			F.read(x);
			int l=L,r=R,mid;
			while (l<=r)
				if (a[sa[mid=l+r>>1]+j-1]<x) l=mid+1;
				else r=mid-1;
			int temp=l;
			l=L;
			r=R;
			while (l<=r)
				if (a[sa[mid=l+r>>1]+j-1]<=x) l=mid+1;
				else r=mid-1;
			L=temp;
			R=r;
		}
		if (L<=R) q[++cnt]=(ques) {
			L,R,i
		};
	}
	for (sort(q+1,q+cnt+1),i=L=1,R=0; i<=cnt; ++i) {
		while (L>q[i].l) add(sa[--L],i);
		while (R<q[i].r) add(sa[++R],i);
		while (L<q[i].l) del(sa[L++],i);
		while (R>q[i].r) del(sa[R--],i);
		ans[q[i].id]=ret;
	}
	for (i=1; i<=m; ++i) F.write(ans[i],'\n');
	for (i=1; i<=n; ++i) F.write(t[i],' ');
	return F.Fend(),0;
}

标签:200005,int,P2336,ans,sa,id
From: https://www.cnblogs.com/zan-mei-tai-yang/p/18444970

相关文章

  • P2336 [SCOI2012] 喵星球上的点名 解题报告
    oj:https://gxyzoj.com/d/gxyznoi/p/P107SA+莫队调了一天,真的心态炸了,总的来说这道题没有一步是好想的首先,看到是多个字符串求一个是另一个子串,显然想到,讲这些字符串拼接起来,因为姓和名不能连在一起,所以可以在他们中间加一个没有出现的数字接下来,首先考虑第一个问题在拼接完后......
  • 【SA+莫队】P2336 [SCOI2012]喵星球上的点名
    [SCOI2012]喵星球上的点名题目描述a180285幸运地被选做了地球到喵星球的留学生。他发现喵星人在上课前的点名现象非常有趣。假设课堂上有\(n\)个喵星人,每个喵星人的......