当前位置:主页 > 查看内容

洛谷P7480 四月赛 Reboot from Blue

发布时间:2021-05-10 00:00| 位朋友查看

简介:题目 题目链接 解题思路 首先油价是大于0的油箱是无限的。因此我们不会从油价低的地方到油价高的地方去加油。我们可以根据每个地方油价的从高到低依次更新。 考虑某次到达点t后其油价是v那么对另一点s的贡献是v*abs(t-s)。这是两条直线。 考虑到我们是动态的……

题目

在这里插入图片描述
题目链接

解题思路

首先油价是大于0的,油箱是无限的。因此我们不会从油价低的地方到油价高的地方去加油。我们可以根据每个地方油价的从高到低依次更新。
考虑某次到达点t后,其油价是v,那么对另一点s的贡献是v*abs(t-s)。这是两条直线。
考虑到我们是动态的确定点,并添加直线,因此维护下凸壳即可。
使用线段添加的李超树,复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;

#define lson rt * 2
#define rson rt * 2 + 1

typedef long long ll;

const int N = 1e5 + 100;

int n, s, t, tp, cnt;
int has[N], val[N];
ll dp[N];

struct Line {
	ll k, b;
	Line() { k = 0; b = 1e18; }
	Line(ll k, ll b) :k(k), b(b) {}
	ll cal(ll x) {
		return k * x + b;
	}
}tree[N * 4];

void insert(Line x, int l, int r, int rt) {
	int m = (l + r) / 2;
	if (tree[rt].cal(has[m]) > x.cal(has[m])) swap(tree[rt], x);
	if (l == r) return;
	if (tree[rt].cal(has[l]) > x.cal(has[l])) insert(x, l, m, lson);
	else insert(x, m + 1, r, rson);
}

void insert(int rl, int rr, Line x, int l, int r, int rt) {
	if (rl == l && rr == r) return void(insert(x, l, r, rt));
	int m = (l + r) / 2;
	if (rr <= m) insert(rl, rr, x, l, m, lson);
	else if (m < rl) insert(rl, rr, x, m + 1, r, rson);
	else {
		insert(rl, m, x, l, m, lson);
		insert(m + 1, rr, x, m + 1, r, rson);
	}
}

void query(int id, Line &res, int l, int r, int rt) {
	if (tree[rt].cal(has[id]) < res.cal(has[id])) res = tree[rt];
	if (l == r) return;
	int m = (l + r) / 2;
	if (id <= m) query(id, res, l, m, lson);
	else query(id, res, m + 1, r, rson);
}

struct node {
	int w, id;
}sa[N];

bool operator < (node a, node b) {
	return a.w > b.w;
}

int get(int id) {
	return lower_bound(has + 1, has + tp + 1, id) - has;
}

int main() {
	//freopen("0.txt", "r", stdin);
	scanf("%d%d%d", &n, &s, &t);
	for (int i = 1; i <= n; i++) scanf("%d%d", &sa[i].w, &sa[i].id), has[++tp] = sa[i].id;
	has[++tp] = s; has[++tp] = t;
	sort(has + 1, has + tp + 1);
	tp = unique(has + 1, has + tp + 1) - has - 1;
	memset(val, 0x3f3f3f3f, sizeof(val));
	s = get(s); t = get(t);
	for (int i = 1; i <= n; i++) {
		sa[i].id = get(sa[i].id);
		val[sa[i].id] = min(val[sa[i].id], sa[i].w);
		if (sa[i].id == s) sa[i].w = 0;
	}
	sort(sa + 1, sa + n + 1);
	insert(s, tp, Line(val[s], -1LL * has[s] * val[s]), 1, tp, 1);
	insert(1, s, Line(-val[s], 1LL * has[s] * val[s]), 1, tp, 1);
	for (int i = 1; sa[i].w; i++) {
		if (sa[i].w != val[sa[i].id]) continue;
		Line res; int id = sa[i].id;
		query(id, res, 1, tp, 1);
		dp[id] = res.cal(has[id]);
		insert(1, id, Line(-val[id], dp[id] + 1LL * has[id] * val[id]), 1, tp, 1);
		insert(id, tp, Line(val[id], dp[id] - 1LL * has[id] * val[id]), 1, tp, 1);
	}
	Line res;
	query(t, res, 1, tp, 1);
	printf("%lld\n", res.cal(has[t]));
	return 0;
}
;原文链接:https://blog.csdn.net/qq_39586831/article/details/115447425
本站部分内容转载于网络,版权归原作者所有,转载之目的在于传播更多优秀技术内容,如有侵权请联系QQ/微信:153890879删除,谢谢!

推荐图文


随机推荐