可能我不适合做NOI题
什么水题都做不了
题目链接:右转进入题目
题目大意:请自行参考原题
题解:
首先把前面随机数据生成的部分完全暴力的敲出来
然而我这部分因为内存开小了不停地出各种奇奇怪怪的bug
到最后都怀疑是不是不适合编程
显然,敲完生成的棋盘之后,可以知道(1,1)和(n,m)是一定要选的。
下一个选什么呢?显然,从1开始考虑到n*m(应该注意到T的值是从1~n*m),如果能选就选。
因为要从小到大考虑,所以要对T排序后记录一下排名。
具体点说,如果选择了(i,j)这个点,那么它的左下角和右上角都不能选了,就把他们覆盖掉。
所以可以用一个支持矩阵加和单点修改的BIT。复杂度O(n^2lg^2n)
加上一开始排序的快排的O(n^2lgn),总复杂度O(n^2lg^2n)。
不好
考虑优化。
注意到程序瓶颈在BIT上。
注意到每个点无论被覆盖了多少次,只要被覆盖了就不能选
注意到每次覆盖操作都是一个前缀矩阵。
换句话说,如果一个点被覆盖了,(暂且只考虑左下角的矩阵),那么他的左下角一定都被覆盖了。
换句话说,当我们进行覆盖操作的时候(还是只考虑(i,j)左下角),从i+1行到n行,每行从右到左染色,
如果染色到一个已经覆盖的点就停止。
特别的如果(i+1,j-1)也被覆盖了,这次覆盖操作就不用进行了。
由于每个店至多被覆盖一次,所以覆盖的复杂度是O(MN)的。
而注意到T的值是从1~MN的,所以可以用桶排
总复杂度O(MN)。
这个题在BZOJ上卡PE,MLE,NOI的时候还卡常数……
我也真是醉了……
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define MAXN 5010
#define MAXM 5010
#define idx(i) ((i-1)/m+1)
#define idy(i) (i-(idx(i)-1)*m)
#define ull long long
using namespace std;
int t[MAXN*MAXM],id[MAXN*MAXM],cnt;
bool chess[MAXN][MAXM];
priority_queue<int> q;
inline void getnum(int &x)
{
x=0;char ch;
while((ch=getchar())<'0'||ch>'9');
x=ch^'0';
while((ch=getchar())>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch-'0');
return;
}
int main()
{
ull x,a,b,c,d;cnt=0;int n,m,Q;
int _x,_a,_b,_c,_d;
scanf("%d%d%d%d%d",&_x,&_a,&_b,&_c,&_d);
x=_x;a=_a;b=_b;c=_c;d=_d;
scanf("%d%d%d",&n,&m,&Q);
for(int i=1;i<=n*m;i++)
t[i]=i;
for(int i=1;i<=n*m;i++)
{
x=(a*x%d*x%d+b*x%d+c)%d;
swap(t[i],t[int(x%i)+1]);
}
while(Q--)
{
int u,v;scanf("%d%d",&u,&v);
swap(t[u],t[v]);
}
for(int i=1;i<=n*m;i++)
id[t[i]]=i;
chess[1][1]=true;q.push(-t[1]);cnt++;
chess[n][m]=true;q.push(-t[n*m]);cnt++;
for(int i=1;i<=n*m&&cnt<n+m-1;i++)
if(!chess[idx(id[i])][idy(id[i])])
{
q.push(-i);cnt++;
for(int j=idx(id[i])+1;j<=n;j++)
if(idy(id[i])-1>=1&&chess[j][idy(id[i])-1]) break;
else for(int k=idy(id[i])-1;k>=1;k--)
if(chess[j][k]) break;
else chess[j][k]=true;
for(int j=idx(id[i])-1;j>=1;j--)
if(idy(id[i])+1<=m&&chess[j][idy(id[i])+1]) break;
else for(int k=idy(id[i])+1;k<=m;k++)
if(chess[j][k]) break;
else chess[j][k]=true;
}
while(!q.empty())
{
int x=-q.top();q.pop();
if(!q.empty()) printf("%d ",x);
else printf("%d\n",x);
}
return 0;
}