昨天月赛T3想问问有没有谷民跟我一个错误
查看原帖
昨天月赛T3想问问有没有谷民跟我一个错误
520544
Phrvth楼主2023/8/27 07:26

sub 4,5的最后一个点WA其他AC,39pts

基本思路是,把 a<ba<b 的点对删掉,初始构造一个 [1,n][1,n] 的序列,然后考虑每一对 a>ba>b 的

把 a,ba,b 当成一条竖直线段,然后将 aa 排序(如果有多条以 aa 为顶点的取最下面(也就是最小的)bb)

然后从后往前遍历,若果遇到可以合并的,就把他合并(具体是,如果两条线段有交集就把他合并),最后得到一条最长的线段,修改它,然后依次遍历,算出答案

有特殊的情况就是从终点下去不需要回来,所以遍历,如果这条线段符合 top−bi≤(ai−bi)×2top-b_i \le (a_i-b_i)\times 2 的话,找到第一个,然后构造以 toptop 为定点,bib_i 为底点的线段,算即可

这里贴出代码:

#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;
}
2023/8/27 07:26
加载中...