@ZCDHJ
2019-09-21T12:20:31.000000Z
字数 1554
阅读 616
未分类
对于一组 可以看成表示与第 个人同分的人的区间是 。那么将一定假的情况先剔除,接下来可以将问题看成是选择若干个不相交的区间,使得区间的权值和最大。使用树状数组优化 DP 即可。
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>const int MAXN = 100000;int n, a[MAXN | 1], b[MAXN | 1], dp[MAXN | 1], bit[MAXN | 1];struct Range {int l, r, res;Range() : l(0), r(0), res(0) {}Range(int _l, int _r) : l(_l), r(_r) {}friend bool operator< (const Range &lhs, const Range &rhs) {return lhs.l < rhs.l || (lhs.l == rhs.l && lhs.r < rhs.r);}} range[MAXN | 1], tm[MAXN | 1];inline bool comp(const Range &lhs, const Range &rhs) {return lhs.r < rhs.r;}inline int read() {register int x = 0;register char ch = getchar();while (!isdigit(ch)) ch = getchar();while (isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}return x;}void modify(int x, int y) {if (x <= 0) x = 1;while (x <= n) {bit[x] = std::max(bit[x], y);x += x & (-x);}}int query(int x) {int res = 0xcfcfcfcf;// printf("res=%d\n", res);while (x > 0) {res = std::max(res, bit[x]);x -= x & (-x);}return res;}int main() {n = read();for (int i = 1; i <= n; ++i) {a[i] = read();b[i] = read();}for (int i = 1; i <= n; ++i) {range[i].l = a[i] + 1;range[i].r = n - b[i];}std::sort(range + 1, range + 1 + n);int tot = 0;for (int i = 1; i <= n; ++i) {if (range[i].l > range[i].r) continue;if (range[i].l != range[i - 1].l || range[i].r != range[i - 1].r) {tm[++tot].l = range[i].l;tm[tot].r = range[i].r;tm[tot].res = 1;} else {tm[tot].res += 1;if (tm[tot].res > tm[tot].r - tm[tot].l + 1) tm[tot].res = tm[tot].r - tm[tot].l + 1;}}std::sort(tm + 1, tm + 1 + tot, comp);memset(bit, 0xcf, sizeof(bit));dp[tm[1].r] = tm[1].res;modify(tm[1].r, tm[1].res);for (int i = 2; i <= tot; ++i) {dp[tm[i].r] = std::max(query(tm[i].l - 1), 0) + tm[i].res;modify(tm[i].r, dp[tm[i].r]);}printf("%d\n", n - query(tm[tot].r));return 0;}