贪心 BZOJ 3671:[Noi2014]随机数生成器

Description

 

Input

第 1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子。第2行包含三个整数 N,M,Q ,表示小H希望生成一个1到 N×M 的排列来填入她 N 行 M 列的棋盘,并且小H在初始的 N×M 次交换操作后,又进行了 Q 次额外的交换操作。接下来 Q 行,第 i 行包含两个整数 u_i,v_i,表示第 i 次额外交换操作将交换 T_(u_i )和 T_(v_i ) 的值。

Output

输出一行,包含 N+M-1 个由空格隔开的正整数,表示可以得到的字典序最小的路径序列。

Sample Input

1 3 5 1 71
3 4 3
1 7
9 9
4 9

Sample Output

1 2 6 8 9 12

HINT

本题的空间限制是 256 MB,请务必保证提交的代码运行时所使用的总内存空间不超过此限制。

一个32位整数(例如C/C++中的int和Pascal中的Longint)为4字节,因而如果在程序中声明一个长度为 1024×1024 的32位整型变量的数组,将会占用 4 MB 的内存空间。



2≤N,M≤5000

0≤Q≤50000

0≤a≤300

0≤b,c≤108

0≤x0<d≤1081≤ui,vi≤N×M




   这题先生成数据,应用贪心的思想,优先取字典序最小的,然后删除排除的情况,总之换个角度看就水过了。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 using namespace std;
 5 int n,m,Q;
 6 long long x,a,b,c,d;
 7 long long Getnxt(){
 8     return (1ll*a*x*x+1ll*b*x+1ll*c)%d;
 9 }
10 const int maxn=5010;
11 
12 int map[maxn][maxn];
13 int pos[maxn*maxn];
14 int U[maxn],D[maxn],L[maxn],R[maxn];
15 
16 int main(){
17     scanf("%lld%lld%lld%lld%lld",&x,&a,&b,&c,&d);
18     scanf("%d%d%d",&n,&m,&Q);
19     for(int i=1;i<=n;i++)
20         for(int j=1,p;j<=m;j++){
21             x=Getnxt();
22             p=x%(1ll*(i-1)*m+j)+1;
23             map[i][j]=(i-1)*m+j;
24             swap(map[i][j],map[(p-1)/m+1][(p-1)%m+1]);    
25         }
26     for(;Q--;){
27         int u,v;
28         scanf("%d%d",&u,&v);
29         swap(map[(u-1)/m+1][(u-1)%m+1],map[(v-1)/m+1][(v-1)%m+1]);
30     }    
31     for(int i=1;i<=n;i++)
32         for(int j=1;j<=m;j++)    
33             pos[map[i][j]]=(i-1)*m+j;
34     
35     int cnt=0,x,y;
36     
37     for(int i=1;i<=n;i++)
38         R[i]=m+1;
39     for(int i=1;i<=m;i++)
40         D[i]=n+1;    
41     for(int i=1;i<=n*m;i++){
42         x=(pos[i]-1)/m+1;y=(pos[i]-1)%m+1;
43         if(y>L[x]&&y<R[x]&&x>U[y]&&x<D[y]){
44             ++cnt;
45             for(int j=x+1;j<=n;j++)
46                 L[j]=max(L[j],y-1);
47             for(int j=x-1;j>=1;j--)    
48                 R[j]=min(R[j],y+1);
49             for(int j=y+1;j<=m;j++)    
50                 U[j]=max(U[j],x-1);
51             for(int j=y-1;j>=1;j--)
52                 D[j]=min(D[j],x+1);
53             
54             if(cnt!=n+m-1)
55                 printf("%d ",i);
56             else
57                 printf("%d",i);
58         }
59         if(cnt==n+m-1)
60             break;
61     }
62     return 0;
63 }
尽最大的努力,做最好的自己!
原文地址:https://www.cnblogs.com/TenderRun/p/5302393.html