→题目链接←
【想说的话】
再次手误...
【题解】
对于每个区间维护四种最大值
1、选左端点不选右端点
2、选右端点不选左端点
3、两个端点都选
4、两个端点都不选
然后用线段树搞一搞就好了
注意下pushup的转移
【代码】
#include<bits/stdc++.h>
#define MAXN 40040
typedef long long ll;
using namespace std;
inline ll rd(){
ll x=0,y=1;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')y=-y;c=getchar();}
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x*y;
}
struct node{
int l,r;
int Maxlr,Maxl,Maxr,Max;
}tree[MAXN*4];
int n,m;
void pushup(int x){
int l=x*2,r=x*2+1;
tree[x].Maxlr=max(tree[l].Maxl+max(tree[r].Maxlr,tree[r].Maxr),tree[r].Maxr+max(tree[l].Maxlr,tree[l].Maxl));
tree[x].Maxl=max(tree[l].Maxlr+tree[r].Max,tree[l].Maxl+max(tree[r].Maxl,tree[r].Max));
tree[x].Maxr=max(tree[r].Maxlr+tree[l].Max,tree[r].Maxr+max(tree[l].Maxr,tree[l].Max));
tree[x].Max=max(tree[l].Max+tree[r].Max,max(tree[l].Maxr+tree[r].Max,tree[l].Max+tree[r].Maxl));
}
void build(int x,int l,int r){
tree[x].l=l;
tree[x].r=r;
if(l==r){
tree[x].Maxlr=rd();
tree[x].Maxl=tree[x].Maxr=tree[x].Max=0;
return;
}
int mid=(l+r)/2;
build(x*2,l,mid);
build(x*2+1,mid+1,r);
pushup(x);
}
void update(int x,int y,ll k){
if(tree[x].l==tree[x].r){
tree[x].Maxlr=k;
tree[x].Maxl=tree[x].Maxr=tree[x].Max=0;
return;
}
int mid=(tree[x].l+tree[x].r)/2;
if(y<=mid)update(x*2,y,k);
else update(x*2+1,y,k);
pushup(x);
}
int main(){
n=rd(),m=rd();
build(1,1,n);
ll ans=0;
while(m--){
int x=rd();
ll y=rd();
update(1,x,y);
ans+=max(tree[1].Max,max(tree[1].Maxl,max(tree[1].Maxr,tree[1].Maxlr)));
}
printf("%lld\n",ans);
return 0;
}