CF1648D Serious Business

由于只能往下走或往右走,那么在走到第三层时决策固定。

因此我们只考虑什么时候从第一层和第二层下来。

定义 \(f_i\) 表示在 \((2,i)\) 时停下的最大权值。

我们枚举我们选择的最后一个操作,设他为 \((l,r,k)\)

那么对于所有 \(i \in [l,r]\) 会有两种转移方式。

一种是 \(f_i = \max(f_i , f_{l-1}+suf_{2,l}-suf_{2,i+1})\)

另一种是 \(f_{i} = \max(f_{i} , pre_{1,j}+suf_{2,j}-suf_{2,i+1}) , j \in [l,i]\)

容易发现 \(-suf_{2,i+1}\) 是常数,可以最后解决。

对于第一种,我们把操作按左端点排序,则可以保证在进行后面的操作时,所有 \(f_{i},i \in [1,l)\) 已经被计算,然后线段树区间取最大值。

对于第二种,在线段树上维护一个左子树对右子树贡献的标记,就可以维护。

可惜考场没写完,大概是省选签到级别?

#include <map>
#include <set>
#include <queue>
#include <cmath>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pii pair <int , int>
#define pll pair <LL , LL>
#define mp make_pair
#define fs first
#define sc second
#define int long long
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

//const int Mxdt=100000; 
//static char buf[Mxdt],*p1=buf,*p2=buf;
//#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;

template <typename T>
void read(T &x) {
	T f=1;x=0;char s=getchar();
	while(s<'0'||s>'9') {if(s=='-') f=-1;s=getchar();}
	while(s>='0'&&s<='9') {x=(x<<3)+(x<<1)+(s-'0');s=getchar();}
	x *= f;
}

template <typename T>
void write(T x , char s='\n') {
	if(!x) {putchar('0');putchar(s);return;}
	if(x<0) {putchar('-');x=-x;}
	T tmp[25]={},t=0;
	while(x) tmp[t++]=x%10,x/=10;
	while(t-->0) putchar(tmp[t]+'0');
	putchar(s); 
}

const int MAXN = 5e5 + 5;
const LL inf = 1e18;

LL tr[MAXN << 2] , Max[MAXN << 2] , tag[MAXN << 2];
LL pre1[MAXN] , suf2[MAXN] , suf3[MAXN] , n , Q;
LL a[5][MAXN];

void build(int l , int r , int now) {
	tr[now] = -inf;tag[now] = inf;
	if(l == r) {
		Max[now] = pre1[l] + suf2[l];
		return;
	}
	int mid = (l + r) >> 1;
	build(l , mid , now << 1);
	build(mid + 1 , r , now << 1 | 1);
	Max[now] = max(Max[now << 1] , Max[now << 1 | 1]);
}

void push_down(int now) {
	if(tag[now] != inf) {
		tr[now << 1 | 1] = max(Max[now << 1] - tag[now] , tr[now << 1 | 1]);
		tag[now << 1] = min(tag[now << 1] , tag[now]);
		tag[now << 1 | 1] = min(tag[now << 1 | 1] , tag[now]);
	}
}

void update(int l , int r , int now , int x , int y , LL val) {
	if(l >= x && r <= y) {
		tr[now] = max(tr[now] , val);
		return;
	}
	push_down(now);
	int mid = (l + r) >> 1;
	if(x <= mid) update(l , mid , now << 1 , x , y , val);
	if(y > mid) update(mid + 1 , r , now << 1 | 1 , x , y , val);
}

void modify(int l , int r , int now , int x , int y , LL k , LL &cur) {
	if(l >= x && r <= y) {
		tr[now] = max(tr[now] , cur - k);
		tag[now] = min(tag[now] , k);
		cur = max(cur , Max[now]);
		return;
	}
	int mid = (l + r) >> 1;
	push_down(now);
	if(x <= mid) modify(l , mid , now << 1 , x , y , k , cur);
	if(y > mid) modify(mid + 1 , r , now << 1 | 1 , x , y , k , cur);
}

LL find(int l , int r , int now , int x) {
	if(l == r) return max(tr[now] , Max[now] - tag[now]);
	LL res = tr[now];
	push_down(now);
	int mid = (l + r) >> 1;
	if(x <= mid) res = max(res , find(l , mid , now << 1 , x));
	else res = max(res , find(mid + 1 , r , now << 1 | 1 , x));
	return res;
}

vector <pii> G[MAXN];
LL f[MAXN];

signed main() {
	read(n),read(Q);
	for (int i = 1; i <= n; ++i) read(a[1][i]) , pre1[i] = pre1[i - 1] + a[1][i];
	for (int i = 1; i <= n; ++i) read(a[2][i]);
	for (int i = n; i >= 1; --i) suf2[i] = suf2[i + 1] + a[2][i];
	for (int i = 1; i <= n; ++i) read(a[3][i]);
	for (int i = n; i >= 1; --i) suf3[i] = suf3[i + 1] + a[3][i];
	
	build(1 , n , 1);
	
	for (int i = 1; i <= Q; ++i) {
		int l , r , k;
		read(l),read(r),read(k);
		G[l].push_back(mp(r , k));
	}
	
	int now = 0;
	f[0] = -inf;
	
	LL ans = -inf;
	
	for (int i = 1; i <= n; ++i) {
		while(now + 1 < i) now ++ , f[now] = find(1 , n , 1 , now) , f[now] -= suf2[now + 1] , ans = max(ans , f[now] + suf3[now]);
		for (int j = 0; j < (int)G[i].size(); ++j) {
			LL r = G[i][j].fs , k = G[i][j].sc;
			update(1 , n , 1 , i , r , f[i - 1] + suf2[i] - k);
			LL cur = -inf;
			modify(1 , n , 1 , i , r , k , cur);
		}
	}
	while(now + 1 <= n) now ++ , f[now] = find(1 , n , 1 , now) , f[now] -= suf2[now + 1] , ans = max(ans , f[now] + suf3[now]);
	
	write(ans);
	
	return 0;
}
posted @ 2022-03-06 21:28  Reanap  阅读(114)  评论(0编辑  收藏  举报