【poj3171 Cleaning Shifts】【数据结构优化dp】【最少区间覆盖代价】

【链接】http://poj.org/problem?id=3171

【题意】有N个贴纸,可覆盖范围为[ai,bi],售价ci,问要覆盖L,R,区间,最少需要多少代价

【分析】

dp[i]代表覆盖区间[L,i]的最小花费。

将所有贴纸按右端点排序,设当前贴纸为[ai,bi],价格ci,状态转移方程为:

dp[i]=min{f[x]}+ci    (ai-1<=x<bi)

【初值】dp[L-1]=0;其余为inf

【目标】min(f[bi])(bi>=R)

#include<cstdio>
#include<vector>
#include<algorithm>
#define ll long long 
using namespace std;
const int maxn = 1e6+5;
const int inf = 0x3f3f3f3f;

ll dp[maxn];

struct node {int l, r;ll cost;}t[maxn];
int cmp(node a, node b) {return a.r < b.r;}

struct tree {
	int l, r, num;
	ll min;
}tr[maxn<<2];

void build(int p, int l, int r) {
	tr[p].l = l;
	tr[p].r = r;
	tr[p].min = inf;
	if (l == r)return;
	int mid = (l + r) >> 1;
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
}

void update(int p, int id, ll val) {
	if (tr[p].l == tr[p].r) {
		tr[p].min = min(tr[p].min, val);
		return;
	}
	int mid = (tr[p].l + tr[p].r) >> 1;
	if (id <= mid) update(p << 1, id, val);
	else update(p << 1 | 1, id, val);
	tr[p].min = min(tr[p << 1].min, tr[p << 1 | 1].min);
}

ll query(int p, int l, int r) {
	if (tr[p].l >= l && tr[p].r <= r) return tr[p].min;
	int mid = (tr[p].l + tr[p].r) >> 1;
	if (r <= mid)return query(p << 1, l, r);
	else if(l>mid)return query(p << 1 | 1, l, r);
	else return min(query(p << 1, l, r), query(p << 1 | 1, l, r));
}

int main() {
	int n, l,r;
	int f = 0;
	scanf("%d%d%d", &n, &l, &r);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d%d", &t[i].l, &t[i].r, &t[i].cost);
	}
	sort(t + 1, t + 1 + n, cmp);
	build(1, 1, r + 1);
	memset(dp, inf, sizeof(dp));
	for (int i = 1; i <= n; i++) {
		if (t[i].r < l)continue;
		if (t[i].l <= l) {
			dp[t[i].r] = min(dp[t[i].r], t[i].cost);
		}
		else {
			dp[t[i].r] = min(dp[t[i].r], query(1, t[i].l, t[i].r) + t[i].cost);
		}
		update(1, t[i].r + 1, dp[t[i].r]);
	}
	ll ans = inf;
	for (int i = r; i <= t[n].r; i++) {
		ans = min(ans, dp[i]);
	}
	if (ans >= inf) {
		printf("-1\n");
	}
	else printf("%lld\n", ans);
}

猜你喜欢

转载自blog.csdn.net/running_acmer/article/details/82110805