do_while_true

一言(ヒトコト)

「题解」洛谷 P7867 「EVOI-RD1」马戏团

\(f_i\) 为仅考虑前 \(i\) 个位置的答案。

\(f_i=\max\{f_j-sum(j+1,i)+calc(j+1,i),f_{i-1}\}\)

\(sum(j+1,i)\)\(c\) 区间和,\(calc(i,j)\) 为完全在 \([i,j]\) 中的演出收益和。

做一个扫描线(或者叫线段树优化 dp)即可解决。

#include<iostream>
#include<cstdio>
#include<vector>
#include<set>
#include<algorithm>
#define pb push_back
#define mp std::make_pair
#define fir first
#define sec second
typedef std::pair<int, int> pii;
typedef std::vector<int> veci;
typedef std::vector<pii> vecpii;
typedef long long ll;
ll Abs(ll x) { return x < 0 ? -x : x; }
ll Max(ll x, ll y) { return x > y ? x : y; }
template <typename T>
T& read(T& r) {
    r = 0; bool w = 0; char ch = getchar();
    while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
    return r = w ? -r : r;
}
const int N = 2000100;
int n, m;
ll c[N], f[N];
#define ls tree[x].lson
#define rs tree[x].rson
#define tl tree[x].l
#define tr tree[x].r
int trnt;
struct SGT {
	int l, r, lson, rson;
	ll mx, tag;
}tree[N << 1];
inline void pushup(int x) { tree[x].mx = Max(tree[ls].mx, tree[rs].mx); }
inline void pushdown(int x) {
	if(tree[x].tag) {
		ll p = tree[x].tag;
		tree[ls].mx += p; tree[rs].mx += p; 
		tree[ls].tag += p; tree[rs].tag += p;
		tree[x].tag = 0;
	}
}
int build(int l, int r) {
	int x = ++trnt;
	tl = l; tr = r;
	if(l == r) return x;
	ls = build(l, (l+r)>>1); rs = build(tree[ls].r+1, r);
	pushup(x); return x;
}
void modify(int x, int l, int r, ll v) {
	if(tl >= l && tr <= r) {
		tree[x].mx += v;
		tree[x].tag += v;
		return ;
	}
	int mid = (tree[x].l + tree[x].r) >> 1;
	pushdown(x);
	if(mid >= l) modify(ls, l, r, v);
	if(mid < r) modify(rs, l, r , v);
	pushup(x);
}
ll query(int x, int l, int r) {
	if(tl >= l && tr <= r) return tree[x].mx;
	int mid = (tree[x].l + tree[x].r) >> 1; ll sumq = 0;
	pushdown(x);
	if(mid >= l) sumq = Max(sumq, query(ls, l, r));
	if(mid < r) sumq = Max(sumq, query(rs, l, r));
	pushup(x);
	return sumq;
}
void Modify(int l, int r, ll v) { modify(1, l+1, r+1, v); }
ll Query(int l, int r) { return query(1, l+1, r+1); }
#undef ls
#undef rs
#undef tl
#undef tr
struct Node {
	int l, r;
	ll v;
}q[N];
bool cmp(Node x, Node y) {
	return x.r < y.r;
}
signed main() {
	read(n); read(m);
	for(int i = 1; i <= n; ++i) read(c[i]);
	build(1, n+1);
	for(int i = 1; i <= m; ++i) read(q[i].l), read(q[i].r), read(q[i].v);
	std::sort(q + 1, q + m + 1, cmp);
	int top = 1;
	for(int i = 1; i <= n; ++i) {
		Modify(0, i-1, -c[i]);
		while(q[top].r == i && top <= m) {
			Modify(0, q[top].l-1, q[top].v);
			++top;
		}
		f[i] = Query(0, i-1);
		f[i] = Max(f[i], f[i-1]);
		Modify(i, i, f[i]);
	}
	printf("%lld\n", f[n]);
	return 0;
}
posted @ 2021-09-22 21:25  do_while_true  阅读(38)  评论(0编辑  收藏  举报