注意暴力双端队列+桶计算时,一轮中可能对某个长为 1 0 5 10^5 105的小串反复插入,会T。
判断字符串相同的条件比较特殊:每个数字出现次数相同则字符串相同。桶可以转成哈希—— b a s e base base进制的每一位系数分别表示这个位数的出现次数。
记录每个小串的整体哈希值,插入删除就是 O ( 1 ) O(1) O(1)的。
首先暴力前几轮(一轮指的是完整的 m m m次操作),使得小串连接总长 ≥ T \geq T ≥T,后面每轮都是等价的,再多进行一轮算一下每次操作的贡献即可。
#include
#define pii pair
#define mkp make_pair
#define fi first
#define sc second
#define gc getchar
#define pb push_back
using namespace std;
const int N=1e5+10,p1=1e9+7,p2=1e9+9,bs=1e5+7;
typedef long long ll;
typedef double db;
int n,T,q,m,R[N],sz[N],a[N];
int r[N],gx[N],rnd,L,t[N];
pii pw[N],ori,v,nw;ll ans,whl;
vector<pii>hz[N];
char cp;
inline int rd()
{
cp=gc();int x=0,f=1;
for(;!isdigit(cp);cp=gc()) if(cp=='-') f=-1;
for(;isdigit(cp);cp=gc()) x=x*10+(cp^48);
return f*x;
}
inline int ad(int x,int y,int p){
x+=y;return x>=p?x-p:x;}
inline int dc(int x,int y,int p){
x-=y;return x<0?x+p:x;}
inline pii operator *(pii a,int b){
return mkp((ll)a.fi*b%p1,(ll)a.sc*b%p2);}
inline pii operator +(pii a,int b){
return mkp(ad(a.fi,b,p1),ad(a.sc,b,p2));}
inline pii operator +(pii a,pii b){
return mkp(ad(a.fi,b.fi,p1),ad(a.sc,b.sc,p2));}
inline pii operator -(pii a,pii b){
return mkp(dc(a.fi,b.fi,p1),dc(a.sc,b.sc,p2));}
inline pii operator *(pii a,pii b){
return mkp((ll)a.fi*b.fi%p1,(ll)a.sc*b.sc%p2);}
struct P{
int id,len;}tp;
deque<P>que;
inline void upd(int x)
{
nw=nw+hz[x][sz[x]];L+=sz[x];
que.push_back((P){
x,sz[x]});
for(;L>T;){
tp=que.front();que.pop_front();nw=nw-hz[tp.id][tp.len];
if(L-tp.len>=T) L-=tp.len;else{
nw=nw+hz[tp.id][T-L+tp.len];
que.push_front((P){
tp.id,T-L+tp.len});L=T;
}
}
}
int main(){
int i,j,x,y,mx=0;pw[0]=mkp(1,1);
for(i=1;i<N;++i) pw[i]=pw[i-1]*bs;
n=rd();T=rd();q=rd();
for(i=1;i<=T;++i) ori=ori+pw[rd()+1];
for(i=1;i<=n;++i){
sz[i]=x=rd();hz[i].resize(x+1);v.fi=v.sc=0;
for(j=1;j<=x;++j) {
a[j]=rd()+1;v=v+pw[a[j]];}
for(j=x;j>0;--j) {
hz[i][j]=v;v=v-pw[a[x-j+1]];}
}
for(m=rd(),i=1;i<=m;++i) whl+=sz[(r[i]=rd())];
rnd=((T-1)/whl+1)*m;
for(i=1;i<=q && i<=rnd;++i){
upd(r[(i-1)%m+1]);ans+=(L==T && ori==nw);}
for(i=1;i<=m && rnd+i<=q;++i){
upd(r[(i-1)%m+1]);gx[i]=gx[i-1]+(ori==nw);}
if(q>rnd) ans+=(ll)gx[m]*((q-rnd)/m)+gx[q%m];
printf("%lld",ans);
return 0;
}
神仙构造题还是不会做 (*  ̄︿ ̄)
官方题解:
数形结合,不妨将原图看做一维直线上的模 p p p意义下的 p p p个点 ( 0 , 1 , . . . , p − 1 ) (0,1,...,p-1) (0,1,...,p−1), p k p^k p