noip模拟22
目录
:<
T1 d
淦!不应该改代码嗷!我以为正解的思路不对会TLE然后打了个DP
我的错误DP思路:设f[i][j]为前i个矩形中删掉了j个矩形时的最大面积, $f[i][j] = max(f[i - 1][j - 1].a * f[i - 1][j - 1].b, min(f[i - 1][j].a, s[i].a) * min(f[i - 1][j].b, s[i].b)$
$f[i][i].a = inf f[i][i].b = inf f[i][i - 1] = s[i] f[i][0].a = min(f[i - 1][0].a, s[i].a) f[i][0].b = min(f[i - 1][0].b, s[i].b)$
然后? 然后大样例88个里对了75个(85.22%)我发现好像n比较大(>500?)的都比答案小。求hack
11pts DP
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
#include <bits/stdc++.h>
#define For(i, l, r) for (int i = (l), i##end = (r); i <= i##end; ++i)
#define Fordown(i, r, l) for (int i = (r), i##end = (l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 1000010;
template <typename type>
type read() {
type s = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * f;
}
struct SQU {
int a, b;
} s[maxn];
struct F {
int a, b;
long long area;
} f[10001][10001];
int n, m, T;
int main() {
freopen("_input", "r", stdin);
freopen("_output", "w", stdout);
T = read<int>();
while (T--) {
n = read<int>();
m = read<int>();
For(i, 1, n) {
s[i].a = read<int>();
s[i].b = read<int>();
}
if (m == 0) {
int mina = 0x3f3f3f3f, minb = 0x3f3f3f3f;
For(i, 1, n) {
mina = min(s[i].a, mina);
minb = min(s[i].b, minb);
}
cout << 1ll * mina * minb << endl;
continue;
}
// f[1][0].area = s[1].a * s[1].b;
f[1][0].a = s[1].a;
f[1][0].b = s[1].b;
f[1][1].a = 0x1f1f1f1f;
f[1][1].b = 0x1f1f1f1f;
For(i, 2, n) {
For(j, i, n) {
f[i][j].a = 0x1f1f1f1f;
f[i][j].b = 0x1f1f1f1f;
}
f[i][0].a = min(f[i - 1][0].a, s[i].a);
f[i][0].b = min(f[i - 1][0].b, s[i].b);
f[i][i - 1].a = s[i].a;
f[i][i - 1].b = s[i].b;
}
For(i, 2, n) {
For(j, 1, min(m, i - 1)) {
if (1ll * f[i - 1][j - 1].a * 1ll * f[i - 1][j - 1].b >
1ll * min(f[i - 1][j].a, s[i].a) * 1ll *
min(f[i - 1][j].b, s[i].b)) {
f[i][j].area = 1ll * f[i - 1][j - 1].a * 1ll * f[i - 1][j - 1].b;
f[i][j].a = f[i - 1][j - 1].a;
f[i][j].b = f[i - 1][j - 1].b;
} else {
f[i][j].area = 1ll * min(f[i - 1][j].a, s[i].a) * 1ll *
min(f[i - 1][j].b, s[i].b);
f[i][j].a = min(f[i - 1][j].a, s[i].a);
f[i][j].b = min(f[i - 1][j].b, s[i].b);
}
}
}
long long ans = 0;
For(i, 1, m) {
ans = max(ans, f[n][i].area);
// cout << f[n][i].area << endl;
}
cout << ans << endl;
}
//大样例正确率高达85.227%
return 0;
}
正确解法:真就先按a从大到小排序,从a小的中弹出去m个并标记,再按b从大到小排序,从未标记的数上选出最小的b的位置。接着往回压a,压一个a小的中较大的并取消它的标记,弹一个没被标记过的b(防止弹重)如果现在压进去的点的b小于现在的b,就不用动b的指针了
Accepted
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
#include <bits/stdc++.h>
#define For(i, l, r) for (int i = (l), i##end = (r); i <= i##end; ++i)
#define Fordown(i, r, l) for (int i = (r), i##end = (l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 100010;
template <typename type>
type read() {
type s = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
s = s * 10 + ch - '0';
ch = getchar();
}
return s * f;
}
struct R {
int a, b, id;
} rect[maxn], ma[maxn], mb[maxn];
bool cmpa(R x, R y) {
if (x.a != y.a) return x.a < y.a;
if (x.b != y.b) return x.b < y.b;
return x.id < y.id;
}
bool cmpb(R x, R y) {
if (x.b != y.b) return x.b < y.b;
if (x.a != y.a) return x.a < y.a;
return x.id < y.id;
}
struct S {
int id, val;
};
int T, n, m;
bool vis[maxn];
int main() {
// freopen("_input", "r", stdin);
// freopen("_output", "w", stdout);
T = read<int>();
while (T--) {
n = read<int>();
m = read<int>();
For(i, 1, n) {
rect[i].a = read<int>();
rect[i].b = read<int>();
rect[i].id = i;
ma[i] = mb[i] = rect[i];
}
int mina, minb;
int bptr = 1;
long long ans = 0;
sort(ma + 1, ma + 1 + n, cmpa);
For(i, 1, m) { vis[ma[i].id] = true; }
sort(mb + 1, mb + 1 + n, cmpb);
For(i, 1, n) {
if (!vis[mb[i].id]) {
minb = mb[i].b;
bptr = i;
break;
}
}
ans += 1ll * ma[1 + m].a * mb[bptr].b;
Fordown(i, m, 1) {
vis[ma[i].id] = false;
if (cmpb(ma[i], mb[bptr])) { //a.b<b.b覆盖掉了无需再动b
ans = max(ans, 1ll * ma[1 + i].a * mb[bptr].b);
continue;
}
bptr++;
while (vis[mb[bptr].id]) {
bptr++;
}
ans = max(ans, 1ll * ma[i].a * mb[bptr].b);
}
cout << ans << endl;
}
}