[NOI2014] BZOJ 3671 随机数据生成器-贪心

来源:互联网 发布:sybase删除表字段sql 编辑:程序博客网 时间:2024/06/10 14:32

可能我不适合做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 longusing 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;}


0 0
原创粉丝点击