[NOI2014]随机数生成器(模拟+贪心)

【题解】

先一步步按题目的操得出序列 
然后在方阵中找出最小的数(对于初始方阵是1)的位置(x,y)
再在矩阵(1,1)-(x,y),(x,y)-(n,m)中分别找出最小数的位置 

递归是没必要的,也不容易找出每个子矩阵内最小的数 
可以反过来考虑:
1,2,3……能不能依次使用?
1肯定可以,2的话,必须在1划分出的子矩阵(1,1)-(x,y)或(x,y)-(n,m)中才行 
若2能放入,则2也参与了对可行区域的划分(或者说限制)
之后再判断3……
画图可知,每一行的可行区间是连续的 
这样只需知道每一行的可行区间left[i],right[i],往答案中加入数时维护之即可 


【代码】

用快速乘就TLE了,时限不是5s吗,怎么回事。。。

此题结尾不能输出多余空格

#include<stdio.h>
#include<stdlib.h>
int num[25000005],bel[25000005],left[5005],right[5005];
void jh(int* a,int* b)
{
	int t=*a;
	*a=*b;
	*b=t;
}
int main()
{
	long long a,b,c,d,X;
	int n,m,Q,i,j,k,x,y,cnt;
	scanf("%lld%lld%lld%lld%lld%d%d%d",&X,&a,&b,&c,&d,&n,&m,&Q);
	cnt=n*m;
	for(i=1;i<=cnt;i++)
		num[i]=i;
	for(i=1;i<=cnt;i++)
	{
		X=(a*X%d*X+b*X+c)%d;
		jh(&num[i],&num[(int)X%i+1]);
	}
	for(;Q>0;Q--)
	{
		scanf("%d%d",&i,&j);
		jh(&num[i],&num[j]);
	}
	for(i=1;i<=cnt;i++)
		bel[num[i]]=i;
	for(i=1;i<=n;i++)
	{
		left[i]=1;
		right[i]=m;
	}
	j=0;
	for(i=1;i<=n+m-1;i++)
	{
		do
		{
			j++;
			x=(bel[j]-1)/m+1;
			y=(bel[j]-1)%m+1;
		}
		while(y<left[x]||y>right[x]);
		for(k=1;k<x;k++)
			if(right[k]>y) right[k]=y;
		for(k=x+1;k<=n;k++)
			if(left[k]<y) left[k]=y;
		if(i>1) printf(" ");
		printf("%d",j);
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值