反向贪心决定博弈+博弈论中条件改变人的决策满足单调性:1229A

本文搬运自本人高中时期CSDN博客,若图片加载不出来,可到原文查看:https://blog.csdn.net/zhangtingxiqwq/article/details/135329131

http://cplusoj.com/d/senior/p/SS231229A

结论:

人们倒着来,每个人去掉当前对自己最不利的

因此我们有了 O(n3)O(n^3)

考虑当一个人变了后,每个人的决策必然满足单调性,因此就可以平方了

1
2
start coding at 20:19
passing at 21:18
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
#include <random>
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
//#define int long long
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
#define Z(x) (x) * (x)
#define pb push_back
#define fi first
#define se second
// srand(time(0));
#define N 5010
//#define M
//#define mo
int a[N][N];
void gen(int n, int seed) {
if (seed == 0) {
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n + 1; ++j) a[i][j] = read();
} else {
std::mt19937 rnd(seed);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n + 1; ++j) {
a[i][j] = j;
std::swap(a[i][j], a[i][rnd() % j + 1]);
}
}
}
}
struct node {
int id, x;
bool operator < (const node &A) const {
return x < A.x;
}
};
set<node>s[N];
int n, m, i, j, k, T, seed;
int ans[N], l, lst, b[N], cho[N];

int nxt(int x) {
if(x == 1) return n ;
return x - 1;
}

signed main() {
freopen("sing.in", "r", stdin);
freopen("sing.out", "w", stdout);
#ifdef LOCAL
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
// T=read();
// while(T--) {
//
// }
n = read();
seed = read();
gen(n, seed);
for(i=n; i>=1; --i) {
for(j=1; j<=n+1; ++j) if(!b[j] && (!cho[i] || a[i][j] < a[i][cho[i]])) cho[i]=j;
b[cho[i]]=1;
// debug("%d : %d\n", i, cho[i]);
}
// for(j=1; j<=n; ++j) debug("%d ", cho[j]); debug("\n");
for(j=1; j<=n+1; ++j) if(!b[j]) break;
printf("%d ", j);
for(i=2, l=n; i<=n; ++i, --l) {
b[cho[l]] = 0;
for(j=nxt(l), lst = cho[l]; j != l; j = nxt(j))
if(a[j][lst] < a[j][cho[j]]) {
b[lst] = 1; b[cho[j]] = 0;
swap(lst, cho[j]);
}
cho[l]=0;
for(j=1; j<=n+1; ++j) if(!b[j] && (!cho[l] || a[l][j] < a[l][cho[l]])) cho[l]=j;
b[cho[l]]=1;
for(j=1; j<=n+1; ++j) if(!b[j]) break;
ans[l]=j;
}
for(i=2; i<=n; ++i) printf("%d ", ans[i]);
return 0;
}