BZOJ3671 [Noi2014]随机数生成器 【贪心】

题目链接

BZOJ3671

题解

模拟题意生成矩阵贪心从小选择即可
每选择一个,就标记其左下右上矩阵
由于每次都是标记一个到边界的矩阵,所以一旦遇到标记过就直接退出即可,可以保证复杂度
还有就是空间和时间有点卡

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
#define res register
using namespace std;
const int maxn = 5005,maxm = 25000005,INF = 1000000000;
inline int read(){
    int out = 0,flag = 1; char c = getchar();
    while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    return out * flag;
}
inline void write(int x){
    if (x / 10) write(x / 10);
    putchar(x % 10 + '0');
}
LL x,a,b,c,d;
int n,m,K,Q,A[maxm],ans[maxn << 1],pos[maxm];
bool vis[maxn][maxn];
int main(){
    x = read(); a = read(); b = read(); c = read(); d = read();
    n = read(); m = read(); Q = read(); K = n * m;
    for (res int i = 1; i <= K; i++){
        *(A + i) = i;
        x = ((a * x + b) * x + c) % d;
        swap(*(A + i),*(A + x % i + 1));
    }
    while (Q--) swap(*(A + read()),*(A + read()));
    for (res int i = 1; i <= K; i++) *(pos + *(A + i)) = i;
    res int cnt = 0,E = n + m,x,y;
    for (res int i = 1; i <= K && cnt < E; i++){
        if (*(pos + i) % m == 0){
            x = *(pos + i) / m;
            y = m;
        }
        else {
            x = *(pos + i) / m + 1;
            y = *(pos + i) % m;
        }
        if (!*(*(vis + x) + y)){
            ans[++cnt] = i;
            if (y < m) for (res int j = x - 1; j; j--){
                if (*(*(vis + j) + y + 1)) break;
                for (res int k = y + 1; k <= m; k++){
                    if (*(*(vis + j) + k)) break;
                    *(*(vis + j) + k) = true;
                }
            }
            if (y > 1) for (res int j = x + 1; j <= n; j++){
                if (*(*(vis + j) + y - 1)) break;
                for (res int k = y - 1; k; k--){
                    if (*(*(vis + j) + k)) break;
                    *(*(vis + j) + k) = true;
                }
            }
        }
    }
    for (res int i = 1; i < E; i++) write(*(ans + i)),putchar(' ');
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mychael/p/9059700.html