sub 4,5的最后一个点WA其他AC,39pts
基本思路是,把 a<b 的点对删掉,初始构造一个 [1,n] 的序列,然后考虑每一对 a>b 的
把 a,b 当成一条竖直线段,然后将 a 排序(如果有多条以 a 为顶点的取最下面(也就是最小的)b)
然后从后往前遍历,若果遇到可以合并的,就把他合并(具体是,如果两条线段有交集就把他合并),最后得到一条最长的线段,修改它,然后依次遍历,算出答案
有特殊的情况就是从终点下去不需要回来,所以遍历,如果这条线段符合 top−bi≤(ai−bi)×2 的话,找到第一个,然后构造以 top 为定点,bi 为底点的线段,算即可
这里贴出代码:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 5e5 + 7, Inf = 1e9 + 7;
int n;
struct Node {
int l, r;
bool operator < (const Node other) const {
if (l == other.l) return r < other.r;
return l < other.l;
}
}A[MAXN], init[MAXN];
int cnt, m;
int L[MAXN], R[MAXN], ans, sum;
void work(int l, int r, int minn) {
int maxx = L[r];
if (maxx == sum) ans += maxx - minn;
else ans += (maxx - minn) * 2;
}
signed main () {
cin >> n;
for (int i = 1, x, y; i <= n; i ++) {
cin >> x >> y, sum = max(sum, max(x, y));
if (x < y) continue;
init[++ cnt] = Node{x, y};
}
sort(init + 1, init + 1 + cnt);
for (int i = 1; i <= cnt; i ++)
if (init[i].l != init[i - 1].l) A[++ m] = Node{init[i].l, init[i].r};
for (int i = 1; i <= m; i ++) L[i] = A[i].l, R[i] = A[i].r;
int x = 0, hh = 0;
for (int i = m; i >= 1; i --) {
if (sum - R[i] <= (L[i] - R[i]) * 2) x = R[i];
}
if (x != 0) L[++ m] = sum, R[m] = x;
int minn = R[m], r = m;
for (int i = m; i >= 0; i --) {
if (L[i] < minn) work(i + 1, r, minn), minn = R[i], r = i;
else minn = min(minn, R[i]);
}
cout << ans + sum << '\n';
return 0;
}