给出一个数组 每个数组的值代表一个集合 相邻的两个集合不能重合 问集合中的最大数是多少
线段树维护这个区间的相邻数的最大值 因为相邻的条件所以边界需要特判
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 100005
#define mid ((l+r)/2)
int a[maxn],b[maxn];
int ma[maxn<<2];
//
void push_up(int x){
ma[x]=max(ma[x<<1],ma[x<<1|1]);
}
void build(int x,int l,int r){
if(l==r){
ma[x]=b[l];
return;
}
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
push_up(x);
}
void change(int x,int l,int r,int xx,int yy){
if(l>xx||r<xx)return;
if(l==r){
ma[x]=yy;
return;
}
change(x<<1,l,mid,xx,yy);
change(x<<1|1,mid+1,r,xx,yy);
push_up(x);
}
int query(int x,int l,int r,int ll,int rr){
if(r<ll||l>rr)return 0;
if(ll<=l&&rr>=r){
return ma[x];
}
return max(query(x<<1,l,mid,ll,rr), query(x<<1|1,mid+1,r,ll,rr));
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)b[i]=a[i]+max(a[i-1],a[i+1]);
build(1,1,n);
while(m--){
int op,l,r;
cin>>op>>l>>r;
if(op==1){
a[l]=r;
if(l>1)
b[l-1]=a[l-1]+max(a[l-2],a[l]);
b[l]=a[l]+max(a[l-1],a[l+1]);
b[l+1]=a[l+1]+max(a[l],a[l+2]);
change(1,1,n,l-1,b[l-1]);
change(1,1,n,l,b[l]);
change(1,1,n,l+1,b[l+1]);
}else{
int ans=0;
if((l+1)<=(r-1))
ans=max(ans,query(1,1,n,l+1,r-1));//只能当区间长度>=2的时候才可
ans=max(ans,a[l]);//处理边界
ans=max(ans,a[r]);//处理边界
if(r==(l+1)){
ans=max(ans,a[l]+a[r]);//答案要求
}
cout<<ans<<'\n';
}
}
}
标签:return,int,max,线段,maxn,ans,define
From: https://www.cnblogs.com/liang302/p/16667722.html