zoukankan      html  css  js  c++  java
  • bzoj 3671 [Noi2014]随机数生成器——贪心(时间复杂度分配)

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

    设 x 为一个点的行号, y 为一个点的列号;原本想着判断一个点能不能选就是看选了的点中 x<cr.x 的 y 的最大值和 x>cr.x 的 y 的最小值,所以想用树状数组维护。

    但这样时间空间都会爆。

    应该发现“选”一个数最多出现 n+m-1 次!所以考虑 O(1) 判断,在选了一个数之后多花时间维护。

    那么可以维护每行能选的列的范围。这个范围一定是一个区间。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=5005;
    int n,m,lm,Q;
    int x[N*N],a[N*N],l[N],r[N];
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    int Mn(int a,int b){return a<b?a:b;}
    int Mx(int a,int b){return a>b?a:b;}
    void init()
    {
      int a,b,c,d;
      x[0]=rdn();a=rdn();b=rdn();c=rdn();d=rdn();
      n=rdn();m=rdn();Q=rdn();
      lm=n*m;
      for(int i=1;i<=lm;i++)
        x[i]=((ll)a*x[i-1]*x[i-1]+(ll)b*x[i-1]+c)%d;
    }
    int main()
    {
      init();
      for(int i=1;i<=lm;i++)a[i]=i;
      for(int i=1;i<=lm;i++)swap(a[i],a[x[i]%i+1]);
      for(int i=1,u,v;i<=Q;i++)
        {
          u=rdn();v=rdn();swap(a[u],a[v]);
        }
      for(int i=1;i<=lm;i++)x[a[i]]=i;
      for(int i=1;i<=n;i++)l[i]=1;for(int i=1;i<=n;i++)r[i]=m;
      for(int i=1,cnt=0,sm=n+m-1;i<=lm;i++)
        {
          int X=(x[i]-1)/m+1,Y=(x[i]-1)%m+1;
          if(Y>r[X]||Y<l[X])continue;
          printf("%d ",i);cnt++;
          if(cnt==lm)break;
          for(int j=1;j<X;j++)r[j]=Mn(r[j],Y);
          for(int j=X+1;j<=n;j++)l[j]=Mx(l[j],Y);
        }
      puts("");return 0;
    }
  • 相关阅读:
    js:数据结构笔记13--检索算法
    ember.js:使用笔记9 开始单元测试
    js:数据结构笔记12--排序算法(2)
    js:数据结构笔记11--排序算法(1)
    js:数据结构笔记10--图和图算法
    js:数据结构笔记9--二叉树
    js:数据结构笔记8--集合
    js:数据结构笔记7--哈希表
    js:数据结构笔记6--字典
    js:数据结构笔记5--链表
  • 原文地址:https://www.cnblogs.com/Narh/p/10132357.html
Copyright © 2011-2022 走看看