P2336
好久没发博客了(因为在家)
看到大家都是用后缀数组+莫队的,于是模仿题解搞了一搞
#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;
}