选择其中卡片总数较少的一类,当相同时选择$t_{1}$所对应的一类(以下记作$A$类)
如果$t_{1}$不是$A$类,就先对$t_{1}$操作一次(即令$a_{1}$减少1)
下面,问题即不断删去$A$类中的一张卡片,再删除另一类中的一张卡片,直至$A$中卡片被删光
事实上,$A$类中卡片删除顺序与最终另一类卡片剩余卡片的位置无关,具体证明考虑交换$A$中两张相邻卡片的删除顺序,并分类讨论来说明不影响即可
由此,不妨假设$A$类卡片是从左到右依次删除(即删完一叠后删除下一叠),每一张删除时都找到下一叠未完全删除的非$A$类卡片,并删除其中一张
对于这个过程,可以用下述方法维护:
记录一个变量$s$,表示$A$中当前还有几张卡片没有对应的删除
若当前为$A$类,令$s$加上这一叠的卡片数
若当前为$B$类,从中删除$min(s,这一叠的卡片数)$,同时$s$也减去这个值
由于是环,所以重复一次即可
时间复杂度为$o(n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 5000005 4 #define mod 1000000007 5 #define ll long long 6 int n,m,p,x,y,seed,base,a[N],t[N],ans[N]; 7 ll s,tot[3]; 8 int rnd(){ 9 int ans=seed; 10 seed=(1LL*seed*base+233)%mod; 11 return ans; 12 } 13 int main(){ 14 scanf("%d%d",&n,&m); 15 int lst=0; 16 for(int i=1;i<=m;i++){ 17 scanf("%d%d%d%d",&x,&y,&seed,&base); 18 for(int j=lst+1;j<=x;j++){ 19 t[j]=rnd()%2+1; 20 a[j]=rnd()%y+1; 21 } 22 lst=x; 23 } 24 for(int i=1;i<=n;i++)tot[t[i]]+=a[i]; 25 if (tot[1]!=tot[2]){ 26 if (tot[1]<tot[2])p=1; 27 else p=2; 28 } 29 else p=t[1]; 30 if (p!=t[1]){ 31 a[1]--; 32 ans[1]++; 33 } 34 for(int i=1;i<=n;i++) 35 if (t[i]==p){ 36 s+=a[i]; 37 ans[i]+=a[i]; 38 a[i]=0; 39 } 40 else{ 41 int x=min((ll)a[i],s); 42 ans[i]+=x; 43 s-=x; 44 a[i]-=x; 45 } 46 for(int i=1;i<=n;i++) 47 if (t[i]==p){ 48 s+=a[i]; 49 ans[i]+=a[i]; 50 a[i]=0; 51 } 52 else{ 53 int x=min((ll)a[i],s); 54 ans[i]+=x; 55 s-=x; 56 a[i]-=x; 57 } 58 ans[0]=1; 59 for(int i=1;i<=n;i++)ans[0]=((ans[i]^(1LL*i*i))+1)%mod*ans[0]%mod; 60 printf("%d",ans[0]); 61 }