1000w的数组,一开始都是2^31-1,然后经过5*10^7次随机位置的随机修改,问你每次的全局最小值。
有效的随机修改的期望次数很少,只有当修改到的位置恰好是当前最小值的位置时才需要扫一下更新最小值。
分个块或者直接暴力都可以。
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> using namespace std; int sz,l[10005],r[10005],sum,num[10000005]; unsigned int x0,x1,a,b,c,A[10000005],minv[10005]; unsigned int next() { unsigned int t = x0 * a + x1 * b + c; x0 = x1; x1 = t; return x0 >> 2; } int n,q; int main(){ // freopen("i.in","r",stdin); cin>>n>>q>>x0>>x1>>a>>b>>c; for(int i=1;i<=n;++i){ A[i]=((unsigned int)1<<31)-1; } sz=sqrt(n); for(sum=1;sum*sz<n;sum++) { l[sum]=(sum-1)*sz+1; r[sum]=sum*sz; for(int i=l[sum];i<=r[sum];i++) num[i]=sum; } l[sum]=sz*(sum-1)+1; r[sum]=n; for(int i=l[sum];i<=r[sum];i++) num[i]=sum; for(int i=1;i<=sum;++i){ minv[i]=((unsigned int)1<<31)-1; } unsigned int nowans=((unsigned int)1<<31)-1; unsigned int base=1; unsigned int ans=0; for(int i=1;i<=q;++i){ base*=(unsigned)10099; unsigned int p=next()%(unsigned int)n; unsigned int former=A[p+1]; A[p+1]=next(); int t=num[p+1]; if(former==minv[t]){ minv[t]=((unsigned int)1<<31)-1; for(int i=l[t];i<=r[t];++i){ minv[t]=min(minv[t],A[i]); } } else if(A[p+1]<minv[t]){ minv[t]=A[p+1]; } if(former==nowans){ nowans=((unsigned int)1<<31)-1; for(int i=1;i<=sum;++i){ nowans=min(nowans,minv[i]); } } else if(A[p+1]<nowans){ nowans=A[p+1]; } ans+=nowans*base; } cout<<ans<<endl; return 0; }