bzoj 3671 随机数生成器 —— 暴力

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3671

原来256M是可以开两个3e7的数组的;

因为答案只有 n+m-1 个数,所以暴力判断能否放即可,不用线段树;

然而 O(n) 判断 O(1) 修改和 O(1) 判断 O(n) 修改是不同的。呵呵。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int const xn=5005,xxn=25000005,xm=5e4+5;
int n,m,t[xxn],ps[xxn],mn[xn],mx[xn];
int rd()
{
  int ret=0,f=1; char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
  while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
  return f?ret:-ret;
}
int mnn(int x,int y){return x<y?x:y;}
int mxx(int x,int y){return x<y?y:x;}
int main()
{
  int xx=rd(),a=rd(),b=rd(),c=rd(),d=rd();
  n=rd(); m=rd(); int Q=rd();
  for(int i=1;i<=n*m;i++)t[i]=i;
  for(int i=1;i<=n*m;i++)
    {
      xx=((ll)a*xx*xx+(ll)b*xx+c)%d;//!%d
      swap(t[i],t[xx%i+1]);
    }
  for(int i=1,u,v;i<=Q;i++)u=rd(),v=rd(),swap(t[u],t[v]);
  for(int i=1;i<=n*m;i++)ps[t[i]]=i;
  for(int i=1;i<=m;i++)mn[i]=1,mx[i]=n;
  int num=0;
  for(int i=1,x,y;i<=n*m;i++)
    {
      x=(ps[i]-1)/m+1; y=(ps[i]-1)%m+1;
      if(mn[y]>x||mx[y]<x)continue;
      printf("%d ",i); num++;
      if(num==n+m-1)break;
      for(int i=1;i<y;i++)mx[i]=mnn(mx[i],x);
      for(int i=y+1;i<=m;i++)mn[i]=mxx(mn[i],x);
    }
  puts("");
  return 0;
}

 

posted @ 2018-12-17 16:50  Zinn  阅读(184)  评论(0编辑  收藏  举报