The 2023 ICPC Asia EC Regionals Online Contest (I) - Problem H. Range Periodicity Query
對于一個周期長度$p$來說,如果它不是$S_k$的周期,那么它一定不是$S_{k+1}$的周期,因此可以二分出分界線$t_p$滿足它是$S_p,S_{p+1},S_{p+2},\dots,S_{t_p}$的周期,但不是$S_{t_p+1}$的周期。對于一個詢問$(k,l,r)$,問題等價于尋找區間中數值最小的數,滿足它的$t$值至少為$k$。將所有詢問按$k$從大到小排序,并將所有周期按$t$值從大到小排序,用線段樹支持單點修改、區間查詢最小值即可。
時間復雜度$\mathcal{O}(n\log n)$。
#include<cstdio>
const int BUF=20000000;
char Buf[BUF],*buf=Buf;
inline void readch(char&a){for(;!((*buf>='a'&&*buf<='z')||(*buf>='A'&&*buf<='Z'));buf++);a=*buf++;}
inline void read(int&a){for(a=0;*buf<48;buf++);while(*buf>47)a=a*10+*buf++-48;}
const int OUT=4000000;
char Out[OUT],*ou=Out;int Outn[30],Outcnt;
inline void write(int x){
if(x<0){
*ou++='-';
x*=-1;
}
if(!x)*ou++=48;
else{
for(Outcnt=0;x;x/=10)Outn[++Outcnt]=x%10+48;
while(Outcnt)*ou++=Outn[Outcnt--];
}
}
inline void writeln(int x){write(x);*ou++='\n';}
const int N=500005,S1=13331,P1=1000000007,S2=233,P2=1000000009;
int n,m,q,i,j,x,y,f[N],st[N],head,tail,cur,que[N][2],ans[N],pos[N],v[1111111];
int p1[N],h1[N*2],p2[N],h2[N*2];
char a[N*2];
int e[N],w[N],nxt[N];
int g[N],nxtq[N];
inline int geth1(int l,int r){return((h1[r]-1LL*h1[l-1]*p1[r-l+1])%P1+P1)%P1;}
inline int geth2(int l,int r){return((h2[r]-1LL*h2[l-1]*p2[r-l+1])%P2+P2)%P2;}
inline int getper(int x){
int l=x+1,r=n,mid,t=x;
while(l<=r){
mid=(l+r)>>1;
int L=st[mid],R=L+mid-1;
if(geth1(L,R-x)==geth1(L+x,R)&&geth2(L,R-x)==geth2(L+x,R))l=(t=mid)+1;else r=mid-1;
}
return t;
}
inline void up(int&a,int b){a>b?(a=b):0;}
void build(int x,int a,int b){
v[x]=N;
if(a==b){
pos[a]=x;
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b);
}
inline void ins(int x,int p){for(x=pos[x];x;x>>=1)up(v[x],p);}
void ask(int x,int a,int b,int c,int d){
if(c<=a&&b<=d){
up(cur,v[x]);
return;
}
int mid=(a+b)>>1;
if(c<=mid)ask(x<<1,a,mid,c,d);
if(d>mid)ask(x<<1|1,mid+1,b,c,d);
}
int main(){
fread(Buf,1,BUF,stdin);
read(n);
head=n+1;
tail=n;
for(i=1;i<=n;i++){
char op;
readch(op);
if(op>='a'&&op<='z')a[--head]=op;
else a[++tail]=op-'A'+'a';
st[i]=head;
}
for(p1[0]=i=1;i<=n;i++)p1[i]=1LL*p1[i-1]*S1%P1;
for(i=head;i<=tail;i++)h1[i]=(1LL*h1[i-1]*S1+a[i])%P1;
for(p2[0]=i=1;i<=n;i++)p2[i]=1LL*p2[i-1]*S2%P2;
for(i=head;i<=tail;i++)h2[i]=(1LL*h2[i-1]*S2+a[i])%P2;
for(i=1;i<=n;i++)f[i]=getper(i);
read(m);
for(i=1;i<=m;i++){
read(x);
y=f[x];
w[i]=x;
nxt[i]=e[y];
e[y]=i;
}
read(q);
for(i=1;i<=q;i++){
read(x);read(que[i][0]);read(que[i][1]);
nxtq[i]=g[x];
g[x]=i;
}
build(1,1,m);
for(i=n;i;i--){
for(j=e[i];j;j=nxt[j])ins(j,w[j]);
for(j=g[i];j;j=nxtq[j]){
cur=N;
ask(1,1,m,que[j][0],que[j][1]);
if(cur>i)cur=-1;
ans[j]=cur;
}
}
for(i=1;i<=q;i++)writeln(ans[i]);
fwrite(Out,1,ou-Out,stdout);
}

浙公網安備 33010602011771號