Processing math: 100%

BZOJ_3671_[Noi2014]随机数生成器_set+贪心

BZOJ_3671_[Noi2014]随机数生成器_set

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到n*m开始枚举,能选则选。

可以发现合法的点集满足横坐标递增的同时纵坐标也递增,考虑用set维护这样的一个点集。

然后我就用O(n2logn)的复杂度水过了这道题。

ps.卡空间,需要把横纵坐标压成一个int。

 

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
#define N 25000500
typedef long long ll;
int P[N],A[N],n,m,Q,a,b,c,d;
struct Point {
    int x,y;
    bool operator < (const Point &p) const {
        return x==p.x?y<p.y:x<p.x;
    }
};
set<Point>S;
bool check(int x,int y) {
    set<Point>::iterator it=S.lower_bound((Point){x,y});
    if(it==S.begin()&&it==S.end()) return 1;
    if(it==S.begin()) {
        return (*it).y>=y;
    }
    if(it==S.end()) {
        it--;
        return (*it).y<=y;
    }
    return (*it).y>=y&&(*(--it)).y<=y;
}
int main() {
    scanf("%d%d%d%d%d%d%d%d",&P[0],&a,&b,&c,&d,&n,&m,&Q);
    register int i,lim=n*m;
    for(i=1;i<=lim;i++) P[i]=(ll(a)*P[i-1]*P[i-1]+ll(b)*P[i-1]+c)%d,A[i]=i;
    for(i=1;i<=lim;i++) swap(A[i],A[P[i]%i+1]);
    int x,y;
    while(Q--) {
        scanf("%d%d",&x,&y); swap(A[x],A[y]);
    }
    int cnt=0;
    for(i=1;i<=lim;i++) P[A[i]]=i;
    for(i=1;i<=lim;i++) {
        x=P[i]%m; if(!x) x=m;
        y=P[i]/m+(x!=m);
        if(check(x,y)) {
            printf("%d",i); cnt++;
            if(cnt==n+m-1) {puts("");return 0;}
            else printf(" ");
            S.insert((Point){x,y});
        }
    }
}

 

posted @   fcwww  阅读(158)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 字符编码:从基础到乱码解决
点击右上角即可分享
微信分享提示