bzoj3671[Noi2014]随机数生成器(贪心)

题面太长就不粘了
贪心思路就是先按值从小到大排序,然后从小往大选可选的数就好
每选一个数,就将这个数的左下方和右下方标记为不可选即可(注意break来保证时间复杂度为 O(n) )。
代码

#include 
#include 
#define maxn 25000005
inline void read(int& x)
{   char c=getchar();x=0;int y=1;
    while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();}
    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    x*=y;
}
long long A,B,C;
int n,m,sum,now,mod,Q,X[maxn],T[maxn];
bool ok[5005][5005],flag;
int main()
{   read(now);scanf("%lld%lld%lld",&A,&B,&C);read(mod);
    register int i,j,k;int x=0,y=0;
    read(n);read(m);read(Q);sum=n*m;
    for(i=1;i<=sum;++i)
    {   now=(A*now*now%mod+B*now%mod+C)%mod;
        X[i]=now;T[i]=i;
    }
    for(i=1;i<=sum;++i) std::swap(T[i],T[X[i]%i+1]);
    for(i=1;i<=Q;++i) read(x),read(y),std::swap(T[x],T[y]);
    for(i=1;i<=sum;++i) X[T[i]]=i;int tmp=n+m-1;
    for(i=1;i<=sum;++i)
    {   int t1=(X[i]-1)/m+1,t2=X[i]-(t1-1)*m;
        if(ok[t1][t2]) continue;
        if(!flag) printf("%d",i),flag=1;
        else printf(" %d",i);
        ok[t1][t2]=1;--tmp;
        for(j=t1-1;j>=1;--j)
        {   if(ok[j][t2+1]) break;
            for(int k=t2+1;k<=m;++k)
            {   if(ok[j][k]) break;
                ok[j][k]=1;
            }
        }
        for(j=t1+1;j<=n;++j)
        {   if(ok[j][t2-1]) break;
            for(k=t2-1;k>=1;--k)
            {   if(ok[j][k]) break;
                ok[j][k]=1;
            }
        }
        if(!tmp) break;
    }
    return 0;
}

Last round

你可能感兴趣的:(贪心)