题解:P14311 【MX-S8-T4】平衡三元组
我们从暴力开始考虑,对于一个确定的区间
感性理解一下,
处理一下区间前/后缀最大值,枚举
进一步思考,当答案最优时,
我们先考虑
接下来我们
如果合法,该答案即为最优答案,因为
如果不合法,我们继续向后重复这个过程,选定
这道题的代码是比较好写的,是一道偏思维的 DS 题。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,a[(int)2e6];
struct Seg{
#define ls i<<1
#define rs i<<1|1
#define mid ((l+r)>>1)
int mx[(int)5e6],pos[(int)5e6],laz[(int)5e6];
void build(int i,int l,int r){
if(l==r)return mx[i]=a[l],pos[i]=l,void();
build(ls,l,mid),build(rs,mid+1,r),push_up(i);
}
void down(int i){
if(!laz[i])return ;
mx[ls]+=laz[i],mx[rs]+=laz[i];
laz[ls]+=laz[i],laz[rs]+=laz[i];laz[i]=0;
}
void push_up(int i){
mx[i]=max(mx[ls],mx[rs]);
pos[i]=mx[i]==mx[ls]?pos[ls]:pos[rs];
}
void add(int i,int l,int r,int x,int y,int k){
if(x<=l&&y>=r)return mx[i]+=k,laz[i]+=k,void();
down(i);if(x<=mid)add(ls,l,mid,x,y,k);
if(y>mid)add(rs,mid+1,r,x,y,k);push_up(i);
}
pair<int,int> query(int i,int l,int r,int x,int y){
if(x<=l&&y>=r)return {mx[i],pos[i]};pair<int,int> ans={-1e9,0};
down(i);if(y<=mid)return query(ls,l,mid,x,y);
if(x>mid)return query(rs,mid+1,r,x,y);
auto [val1,P1]=query(ls,l,mid,x,y);
auto [val2,P2]=query(rs,mid+1,r,x,y);
return {max(val1,val2),val1>=val2?P1:P2};
}int operator [](const int &x){return this->query(1,1,n,x,x).first;}
int operator [](const pair<int,int> x){return this->query(1,1,n,x.first,x.second).first;}
#undef mid
}T;
int ans=0;
void solver(int l,int r,int Mx){
// cout<<l<<' '<<r<<'\n';
if(l>=r)return ;
auto [mx,pos]=T.query(1,1,n,l,r);
if(pos!=l)ans=max(ans,T[{l,pos-1}]+mx+Mx);
if(pos==r)return ;
if(2*mx<=Mx+T[{pos+1,r}])return ans=max(ans,mx+T[{pos+1,r}]+Mx),void();
else solver(pos+1,r,Mx);
}
void solvel(int l,int r,int Mx){
// cout<<l<<' '<<r<<'\n';
if(l>=r)return ;
auto [mx,pos]=T.query(1,1,n,l,r);
if(pos!=r)ans=max(ans,T[{pos+1,r}]+mx+Mx);
if(pos==l)return ;
if(2*mx<=Mx+T[{l,pos-1}])return ans=max(ans,mx+T[{l,pos-1}]+Mx),void();
else solvel(l,pos-1,Mx);
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
// freopen("D.in","r",stdin),freopen("D.out","w",stdout);
cin>>n>>q;
for(int i=1;i<=n;i++)cin>>a[i];
T.build(1,1,n);
for(int i=1,opt,x,y,k;i<=q;i++){
cin>>opt>>x>>y;
if(opt==1){
ans=-1e9;
auto [Mx,Pos]=T.query(1,1,n,x,y);
solvel(x,Pos-1,Mx),solver(Pos+1,y,Mx);
if(ans==-1e9)cout<<"No\n";
else cout<<ans<<'\n';
}else cin>>k,T.add(1,1,n,x,y,k);
}
}