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;
}