题目描述
给出一个含有N个结点的环,编号分别为1..N,环上的点带有权值(可正可负),现要动态的修改某个点的权值,求每次修改后环上的最大连续和,但不能是整个序列的和。
题目大意
单点修改,求环上的最大和。
数据范围
(4<=N,M<=100000)(不会爆int)
样例输入
5
3 -2 1 2 -5
4
2 -2
5 -5
2 -4
5 -1
样例输出
4
4
3
5
解题思路
线段树,维护:↓(最大值与最小值是指这一段的和的最大值与最小值)
Max(区间最大值),MaxL(从左端开始的区间最大值),Maxr(从右端开始的区间最大值)
Min(区间最小值),MinL(从左端开始的区间最小值),Minr(从右端开始的区间最小值)
Sum(区间和),MinMin(这个东西我也不确定是否为必须的,以前做没有修改的环上的最大和时用过的,就加上吧233)
所以对环上最大和的询问的Ans就是(1-n这个区间的最大值)和(Sum-区间最小值)中的最大值A.A
代码
#include <bits/stdc++.h> using namespace std; inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;} int vl[100005],Sum=0,All=0; struct node{ int L,r,Max,MaxL,Maxr,Min,MinL,Minr,Sum,MinMin; }Tree[400005]; void PushUp(int v){ Tree[v].Max=max(Tree[2*v].Max,Tree[2*v+1].Max); Tree[v].Max=max(Tree[2*v].Maxr+Tree[2*v+1].MaxL,Tree[v].Max); Tree[v].MaxL=max(Tree[2*v].MaxL,Tree[2*v].Sum+Tree[2*v+1].MaxL); Tree[v].Maxr=max(Tree[2*v+1].Maxr,Tree[2*v+1].Sum+Tree[2*v].Maxr); Tree[v].Max=max(Tree[v].MaxL,Tree[v].Max); Tree[v].Max=max(Tree[v].Maxr,Tree[v].Max); Tree[v].Min=min(Tree[2*v].Min,Tree[2*v+1].Min); Tree[v].Min=min(Tree[2*v].Minr+Tree[2*v+1].MinL,Tree[v].Min); Tree[v].MinL=min(Tree[2*v].MinL,Tree[2*v].Sum+Tree[2*v+1].MinL); Tree[v].Minr=min(Tree[2*v+1].Minr,Tree[2*v+1].Sum+Tree[2*v].Minr); Tree[v].Min=min(Tree[v].MinL,Tree[v].Min); Tree[v].Min=min(Tree[v].Minr,Tree[v].Min); Tree[v].Sum=Tree[2*v].Sum+Tree[2*v+1].Sum; Tree[v].MinMin=min(Tree[2*v].MinMin,Tree[2*v+1].MinMin); } void Build(int v,int L,int r){ Tree[v]=(node){L,r,-1<<30,-1<<30,-1<<30,1<<30,1<<30,1<<30,0}; if(L==r)return; Build(2*v,L,(L+r)/2); Build(2*v+1,(L+r)/2+1,r); } void Insert(int v,int pos,int val){ if(pos<Tree[v].L||Tree[v].r<pos)return; if(Tree[v].L==Tree[v].r){ Tree[v]=(node){Tree[v].L,Tree[v].r,val,val,val,val,val,val,val,val}; return; } Insert(2*v,pos,val); Insert(2*v+1,pos,val); PushUp(v); } int n; void Solve(int pos,int val){ Sum=Sum-vl[pos]+val; All-=vl[pos]<0; vl[pos]=val; All+=vl[pos]<0; Insert(1,pos,val); int Max=Tree[1].Max,Min=Tree[1].Min; if(All==n)cout<<Max<<"\n"; else{ int Ans=max(Max,Sum-Min); if(Ans==Tree[1].Sum)Ans-=Tree[1].MinMin; cout<<Ans<<"\n"; } } int main(){ n=Getint(); Build(1,1,n); for(int i=1;i<=n;i++)Sum+=vl[i]=Getint(),All+=vl[i]<0; for(int i=1;i<=n;i++)Insert(1,i,vl[i]); int q=Getint(); while(q--){ int pos=Getint(),val=Getint(); Solve(pos,val); } return 0; }
来源:https://www.cnblogs.com/Cedric341561/p/6811014.html