Loading

「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;
}
posted @ 2020-10-28 08:01  SmilingKnight  阅读(54)  评论(0编辑  收藏  举报