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