CF1648D - Serious Business

场上破灭我上红的题。
另外手速场能不能【】啊。

题意:

给定\(3\times n\)的矩阵,\((i,j)\)有权\(a_{i,j}\),走过的格子会强制获得其的权。
只能走过有标记的格子,初始时,只有零二行的格子标记。
你可以花费\(k_i\)的代价,使得第二行的\([l_i,r_i]\)被标记。
\((1,1) \to (3,n)\),最大能获得的权(格子权和减去标记第二行所用的代价)。

做法:

\(f_i\)为走到\((2,i)\)停止的最大权值。

枚举选择的最后一个操作\((l,r,k)\)

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

\(f_i = \max(f_i,pre_{1,j} + suf_{2,j} - suf_{2,i + 1} - k)(j \in [l,i])\)

第一种直接线段树打\(tag\)即可。
第二种即记录\(-k\)的最小值,然后遇到\([l,r]\),把\(g_i = \max g_j\ j \in [l,i - 1]\)即可,这个可以线段树上做。

点击查看代码
#include<bits/stdc++.h>
#define N 500005
#define inf 1e16
#define ll long long 

struct P{
	ll mx1;
	ll pmx,tag;
}T[N * 20];

#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)
#define mx(x) T[x].mx1
#define pmx(x) T[x].pmx
#define tag(x) T[x].tag

ll a[4][N];
ll pre1[N],suf2[N],suf3[N];

int n,q;

inline void up(int u){mx(u) = std::max(mx(ls(u)),mx(rs(u))),pmx(u) = std::max(pmx(ls(u)),pmx(rs(u)));}

inline void build(int u,int l,int r){
//	std::cout<<u<<" "<<l<<" "<<r<<"\n";
	mx(u) = -inf,tag(u) = inf;
	if(l == r){
		pmx(u) = pre1[l] + suf2[l];
		return ;
	}
	build(ls(u),l,mid);
	build(rs(u),mid + 1,r);
	up(u);
//	std::cout<<u<<" "<<l<<" "<<r<<" "<<pmx(u)<<"\n";	
}

inline void down(int u){
	if(tag(u) != inf){
		mx(rs(u)) = std::max(pmx(ls(u)) - tag(u),mx(rs(u)));
		tag(ls(u)) = std::min(tag(ls(u)),tag(u));
		tag(rs(u)) = std::min(tag(rs(u)),tag(u));		
//		std::cout<<"down "<<u<<" "<<mx(rs(u))<<"\n";
	}
}

inline void change(int u,int l,int r,int tl,int tr,ll p){
//	std::cout<<u<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<p<<std::endl; 
	if(tl <= l && r <= tr){
		mx(u) = std::max(mx(u),p);
		return ;
	}
	down(u);
	if(tl <= mid)
	change(ls(u),l,mid,tl,tr,p);
	if(tr > mid)
	change(rs(u),mid + 1,r,tl,tr,p); 
}

inline void modify(int u,int l,int r,int tl,int tr,ll k,ll &cur){
//	std::cout<<u<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<cur<<std::endl; 
	if(tl <= l && r <= tr){
		mx(u) = std::max(mx(u),cur - k);
		tag(u) = std::min(tag(u),k);
		cur = std::max(cur,pmx(u));
		return ;
	}
	down(u);
	if(tl <= mid)
	modify(ls(u),l,mid,tl,tr,k,cur);
	if(tr > mid)
	modify(rs(u),mid + 1,r,tl,tr,k,cur);	
}

inline ll find(int u,int l,int r,int p){
//	std::cout<<"FIND "<<u<<" "<<l<<" "<<r<<" "<<p<<std::endl; 	
	if(l == r){
		return std::max(mx(u),pmx(u) - tag(u));
	}
	ll res = mx(u);
	down(u);
	if(p <= mid)
	res = std::max(res,find(ls(u),l,mid,p));
	if(p > mid)
	res = std::max(res,find(rs(u),mid + 1,r,p));
	return res;
}

using std::vector;
using std::pair;

#define pii pair<int,int>
#define mp std::make_pair 

ll f[N];

vector<pii>G[N];

ll ans = -inf;

int main(){
//	freopen("table1.out","w",stdout);
	scanf("%d%d",&n,&q);
	for(int i = 1;i <= n;++i)
	scanf("%lld",&a[1][i]),pre1[i] = pre1[i - 1] + a[1][i];
	for(int i = 1;i <= n;++i)
	scanf("%lld",&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)
	scanf("%lld",&a[3][i]);
	for(int i = n;i >= 1;--i)
	suf3[i] = suf3[i + 1] + a[3][i];
	build(1,1,n);
	while(q -- ){
		int l,r,k;
		scanf("%d%d%d",&l,&r,&k);
		G[l].push_back(mp(r,k)); 
	}	
	int now = 0;
	f[0] = -inf;
	for(int i = 1;i <= n;++i){
		while(now + 1 < i) now ++ , f[now] = find(1 , 1 , n , now) , f[now] -= suf2[now + 1] , ans = std::max(ans , f[now] + suf3[now]);
		for(auto it : G[i]){
			int r = it.first,k = it.second;
//			std::cout<<i<<" "<<r<<" "<<k<<std::endl;
			change(1,1,n,i,r,f[i - 1] + suf2[i] - k);
			ll cur = -inf;
			modify(1,1,n,i,r,k,cur);
		}
	}
	while(now + 1 <= n) now ++ , f[now] = find(1 , 1 , n , now) , f[now] -= suf2[now + 1] , ans = std::max(ans , f[now] + suf3[now]);	
//	for(int i = 1;i <= n;++i)
//	std::cout<<f[i]<<" ";
//	puts("");
	std::cout<<ans<<"\n";
	return 0;
}



posted @ 2022-03-07 12:14  fhq_treap  阅读(87)  评论(0编辑  收藏  举报