「SCOI2012」喵星球上的点名
「SCOI2012」喵星球上的点名
先咕着,扔个code跑路
code
#include<bits/stdc++.h>
#define vec vector
#define iter iterator
#define REP(i,x,y) for (int i=(x);i<=(y);++i)
#define DWN(i,x,y) for (int i=(x);i>=(y);--i)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
template<class Tp>void ckmin(Tp &x,Tp y){
x=(x<y)?x:y;
}
template<class Tp>void ckmax(Tp &x,Tp y){
x=(x<y)?y:x;
}
template<class Tp>Tp read(){
Tp res=0,f_f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f_f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') res=(res<<3)+(res<<1)+(ch-'0'),ch=getchar();
return res*f_f;
}
#define iread() (read<int>())
#define lread() (read<long long>())
#define uread() (read<unsigned long long>())
const int maxn=20005;
const int maxm=50005;
const int maxz=240005;
const int INF=10007;
struct pii{
int x,y;
pii(){}
pii(int x,int y):x(x),y(y){}
bool operator<(const pii B)const{
if(x^B.x) return x<B.x;
return y<B.y;
}
};
int n,m,s[maxz],idx[maxz],len,tot[maxm];
vec<int> a[maxm];
namespace SA{
int c[maxz],rk[maxz],y[maxz],lg[maxz],id[maxz];
int sa[maxz],height[maxz],st[maxz][22];
int m,n;
inline void build_sa(){
m=INF,n=len;
REP(i,1,m) c[i]=0;
REP(i,1,n) c[rk[i]=s[i]]++;
REP(i,1,m) c[i]+=c[i-1];
DWN(i,n,1) sa[c[rk[i]]--]=i;
for (int k=1;k<=n;k<<=1){
int p=0;
REP(i,n-k+1,n) y[++p]=i;
REP(i,1,n){
if(sa[i]>k) y[++p]=sa[i]-k;
}
REP(i,1,m) c[i]=0;
REP(i,1,n) c[rk[y[i]]]++;
REP(i,1,m) c[i]+=c[i-1];
DWN(i,n,1) sa[c[rk[y[i]]]--]=y[i];
REP(i,1,n) y[i]=rk[i];
p=1,rk[sa[1]]=1;
REP(i,2,n){
int xa=(sa[i-1]+k>n)?-1:y[sa[i-1]+k];
int xb=(sa[i]+k>n)?-1:y[sa[i]+k];
rk[sa[i]]=(xa==xb&&y[sa[i]]==y[sa[i-1]])?p:++p;
}
if(p>=n) break;
m=p;
}
REP(i,1,n) id[i]=idx[sa[i]];
}
inline void build_height(){
int k=0;
n=len,height[1]=0;
REP(i,1,n){
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;
}
}
inline void build_LCP(){
lg[1]=0,n=len;
REP(i,2,n) lg[i]=lg[i>>1]+1,st[i][0]=height[i];
for (int j=1;(1<<j)<=n;j++){
for (int i=1;i+(1<<j)-1<=n;i++){
st[i][j]=st[i][j-1];
ckmin(st[i][j],st[i+(1<<(j-1))][j-1]);
}
}
}
inline int get_LCP(int x,int y){
if(x>y) swap(x,y);
x++;
int i=lg[y-x+1];
return min(st[x][i],st[y-(1<<i)+1][i]);
}
int lst,lcur;
inline int suffix_cmp(int x,int p){
if(lst){
int cur=get_LCP(lst,p);
if(cur>=lcur){
int i=lcur+1;
while(i<=tot[x]&&a[x][i]==s[sa[p]+i-1]) i++;
if(i-1>lcur) lst=p,lcur=i-1;
if(i==tot[x]+1) return 2;
return s[sa[p]+i-1]>a[x][i];
}
return s[sa[p]+cur]>a[x][cur+1];
}
int i=1;
while(i<=tot[x]&&a[x][i]==s[sa[p]+i-1]) i++;
lst=p,lcur=i-1;
if(i==tot[x]+1) return 2;
return s[sa[p]+i-1]>a[x][i];
}
inline pii match(int x){
pii res=pii(len+1,0);
int L=1,R=len,mid;
lst=0,lcur=0;
while(L<=R){
mid=L+R>>1;
int bnow=suffix_cmp(x,mid);
if(bnow^1) res.y=mid,L=mid+1;else R=mid-1;
}
L=1,R=len,lst=0,lcur=0;
while(L<=R){
mid=L+R>>1;
int bnow=suffix_cmp(x,mid);
if(bnow) res.x=mid,R=mid-1;else L=mid+1;
}
return res;
}
}
struct Mo{
int x,y,id,ans,idl;
}b[maxm];
inline bool cmp1(Mo x,Mo y){
if(x.idl^y.idl) return x.idl<y.idl;
return (x.idl&1)?(x.y<y.y):(x.y>y.y);
}
inline bool cmp2(Mo x,Mo y){
return x.id<y.id;
}
int buk[maxn],tp[maxn],ans[maxn],cnt,bsiz;
inline void update(int x,int k,int id){
if(k){
if(!buk[x]) tp[x]=id,cnt++;
buk[x]++;
}
else{
buk[x]--;
if(!buk[x]) ans[x]+=id-tp[x],cnt--;
}
}
int main(){
n=iread(),m=iread(),len=0;
REP(i,1,n){
int x=iread();
REP(j,1,x) s[++len]=iread(),idx[len]=i;
s[++len]=INF,x=iread();
REP(j,1,x) s[++len]=iread(),idx[len]=i;
s[++len]=INF;
}
SA::build_sa();
SA::build_height();
SA::build_LCP();
bsiz=(int)sqrt(len)+1;
REP(i,1,m){
tot[i]=iread(),a[i].push_back(0);
REP(j,1,tot[i]){
int x=iread();
a[i].push_back(x);
}
a[i].push_back(-1);
pii res=SA::match(i);
b[i].x=res.x,b[i].y=res.y,b[i].id=i;
b[i].ans=0,b[i].idl=(b[i].x-1)/bsiz+1;
}
sort(b+1,b+m+1,cmp1);
int pl=1,pr=0,mt=0;
cnt=0;
REP(i,1,m){
if(b[i].x>b[i].y) continue;
mt++;
while(pr<b[i].y) update(SA::id[++pr],1,mt);
while(pl>b[i].x) update(SA::id[--pl],1,mt);
while(pr>b[i].y) update(SA::id[pr--],0,mt);
while(pl<b[i].x) update(SA::id[pl++],0,mt);
b[i].ans=cnt;
}
REP(i,1,n){
if(!buk[i]) continue;
ans[i]+=mt-tp[i]+1;
}
sort(b+1,b+m+1,cmp2);
REP(i,1,m) printf("%d\n",b[i].ans);
REP(i,1,n){
if(i^n) printf("%d ",ans[i]);
else printf("%d\n",ans[i]);
}
return 0;
}