题目
题意:给定一座山,高度为d;给定n个人,跳高能力为
s
i
s_i
si,当第i个人跳过山后,山的高度会变成
d
=
m
a
x
(
d
,
a
i
)
d=max(d,a_i)
d=max(d,ai);一个人能跳过山,当前仅当他的
s
i
>
=
d
s_i>=d
si>=d。问怎么排这n个人的过山顺序,使得能过山的人最多。
官方题解
2700的贪心,我愿称之为最强贪心。(开始翻译题解QAQ)
-
显然,所有 s i < d s_i<d si<d,可以不考虑。
-
定义序列 p 1 , p 2 , . . . , p k p_1,p_2,...,p_k p1,p2,...,pk,为完美序列,如果对于每个 i i i,有 m a x ( d , a p 1 , . . . , a p i − 1 ) < = s p i max(d,a_{p_1},...,a_{p_{i-1}})<=s_{p_i} max(d,ap1,...,api−1)<=spi。
-
对于 a i < = s i a_i<=s_i ai<=si的所有集合,显然是可以构成完美序列。只要将他们按 s i s_i si升序排序即可。
-
对于 a i > s i a_i>s_i ai>si的集合,可以通过贪心获取最大的完美序列集合。按 a i a_i ai排序,每次遇到 s i > = d s_i>=d si>=d,则更新 d = a i d=a_i d=ai,同时 n u m + 1 num+1 num+1。(因为这样保证每次更新d都是取了当前最小的代价 a i a_i ai)
-
考虑点对 i , j i,j i,j,满足 s i < a j < = s j < a i s_i<a_j<=s_j<a_i si<aj<=sj<ai。显然这两个点是冲突的,不能相容于一个完美序列。对于一个可能的完美序列,如果它含有i,那它可以被j代替。 c u r d < s i < s j → s j > c u r d cur_d<s_i<s_j \rightarrow s_j>cur_d curd<si<sj→sj>curd; a j < a i < n x t s → a j < n x t s a_j<a_i<nxt_s \rightarrow a_j<nxt_s aj<ai<nxts→aj<nxts
我们可以预处理,将数据分为
s
i
>
=
a
i
(
p
数
组
)
s_i>=a_i (p数组)
si>=ai(p数组)和
s
i
<
a
i
(
q
数
组
)
s_i<a_i(q数组)
si<ai(q数组)。双指针,遍历p和q,定义集合
M
M
M(按
a
i
a_i
ai降序)。
w
h
i
l
e
(
q
j
.
s
<
p
i
.
a
)
M
.
i
n
s
e
r
t
(
c
j
)
;
while (q_j.s <p_i.a) M.insert(c_j);
while(qj.s<pi.a)M.insert(cj);
w
h
i
l
e
(
M
1
.
a
>
p
i
.
s
)
M
.
e
r
a
s
e
(
M
1
)
while (M_1.a>p_i.s) M.erase(M_1)
while(M1.a>pi.s)M.erase(M1)
通过以上步骤,不在M集合的q数据,则和p数据是冲突的,而在M集合的p数据,不会和q数据冲突。
那么怎么合并p和M数据呢?可以将数据按
(
m
a
x
(
a
i
,
s
i
)
,
s
i
)
(max(a_i,s_i),s_i)
(max(ai,si),si)升序排序。
通过这种排序方式,p数据是按
s
i
s_i
si升序,M数据则处于p数据之间,即
p
i
−
1
.
s
<
(
M
j
.
a
=
m
a
x
(
M
j
.
a
,
M
j
.
s
)
)
<
p
i
.
s
p_{i-1}.s<(M_j.a=max(M_j.a,M_j.s))<p_i.s
pi−1.s<(Mj.a=max(Mj.a,Mj.s))<pi.s,同时M数据是按
a
j
a_j
aj升序。
排好序后,根据上述第4点的贪心规则来取数,就可以达到最大值了。
跟着上述思路码了一波。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
int n, d;
int s[maxn], a[maxn];
int np, nq, nr;
struct node {
int s, a;
bool operator < (const node &x) const {
return a > x.a;
}
}p[maxn], q[maxn], r[maxn];
bool cmp(const node &x, const node &y) {
return x.a < y.a;
}
bool cmp2(const node &x, const node &y) {
return x.s < y.s;
}
bool cmp3(const node &x, const node &y) {
if (max(x.s, x.a) == max(y.s, y.a)) {
return x.s < y.s;
}
return max(x.s, x.a) < max(y.s, y.a);
}
void debug() {
printf("np %d\n", np);
for (int i = 0; i < np; ++i) {
printf("(%d, %d) ", p[i].s, p[i].a);
}
printf("\nnq %d\n", nq);
for (int i = 0; i < nq; ++i) {
printf("(%d, %d) ", q[i].s, q[i].a);
}
printf("\nnr %d\n", nr);
for (int i = 0; i < nr; ++i) {
printf("(%d, %d) ", r[i].s, r[i].a);
}
printf("\n");
}
void pq_init() {
np = 0, nq = 0;
int k = 0;
for (int i = 0; i < n; ++i) {
if (s[i] < d) continue;// remove all s[i] < d
if (s[i] >= a[i]) {
p[np].a = a[i];
p[np].s = s[i];
++np;
} else {
q[nq].a = a[i];
q[nq].s = s[i];
++nq;
}
++k;
}
n = k;
sort(p, p + np, cmp);
sort(q, q + nq, cmp2);
nr = 0;
for (int i = 0; i < np; ++i) {
r[nr++] = p[i];
}
}
int main() {
scanf("%d%d", &n, &d);
for (int i = 0; i < n; ++i) {
scanf("%d%d", &s[i], &a[i]);
}
pq_init();
multiset<node> st;
int j = 0;
for (int i = 0; i < np; ++i) {
while (j < nq && q[j].s < p[i].a) {
st.insert(q[j]);
++j;
}
while (!st.empty() && p[i].s < (*(st.begin())).a) {
st.erase(st.begin());
}
while (!st.empty()) {
r[nr++] = *st.begin();
st.erase(st.begin());
}
}
while (j < nq) {
r[nr++] = q[j];
++j;
}
// if (!np) {
// nr = nq;
// for (int i = 0; i < nq; ++i) {
// r[i] = q[i];
// }
// }
int ans = 0;
sort(r, r + nr, cmp3);
// debug();
for (int i = 0; i < nr; ++i) {
if (d <= r[i].s) {
++ans;
d = max(d, r[i].a);
}
}
printf("%d\n", ans);
}
之后看别人题解,加分析,发现,可以更简单。。贪心yyds啊
#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
int n, d;
int nr;
struct node {
int s, a;
}r[maxn];
bool cmp(const node &x, const node &y) {
if (max(x.s, x.a) == max(y.s, y.a)) {
return x.s < y.s;
}
return max(x.s, x.a) < max(y.s, y.a);
}
int main() {
scanf("%d%d", &n, &d);
for (int i = 0; i < n; ++i) {
scanf("%d%d", &r[i].s, &r[i].a);
}
int ans = 0;
sort(r, r + n, cmp);
for (int i = 0; i < n; ++i) {
if (d <= r[i].s) {
++ans;
d = max(d, r[i].a);
}
}
printf("%d\n", ans);
}