ACWing 245. 你能回答这些问题吗(线段树区间合并)

题目链接 

单点修改,区间查询最大子段和

线段树区间合并模板题

#include
using namespace std;
#define ls (p<<1)
#define rs (ls|1)
#define mid ((t[p].l+t[p].r)>>1)
const int N=500005;

int n;
struct Node{
    int l,r;
	int sum,lans,rans,ans;
}t[N<<2];

inline void pushup(int p){
	t[p].sum=t[ls].sum+t[rs].sum;//区间和
	t[p].lans=max(t[ls].lans,t[ls].sum+t[rs].lans);//区间最大前缀和=max(左子区间最大前缀和,左子区间和+右子区间最大前缀和) 
	t[p].rans=max(t[rs].rans,t[rs].sum+t[ls].rans);//区间最大后缀和=max(右子区间最大后缀和,右子区间和+左子区间最大后缀和)
	t[p].ans=max(max(t[ls].ans,t[rs].ans),t[ls].rans+t[rs].lans);//区间最大子段和=max(左子区间最大子段和,左子区间最大后缀和+右子区间最大前缀和,右子区间最大子段和) 
}

void build(int p,int l,int r) {
    t[p].l=l;
    t[p].r=r;
	if(l==r){
		int x;
		scanf("%d",&x);
		t[p].sum=t[p].lans=t[p].rans=t[p].ans=x;
		return;
	}
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(p);
}

void update(int p,int x,int y){//把下标为x的元素的值改成y
	if(t[p].l==t[p].r){
		t[p].ans=t[p].lans=t[p].rans=t[p].sum=y;
		return;
	}
	if(x<=mid) update(ls,x,y);//p
	else update(rs,x,y);
	pushup(p);//上传节点
}

Node query(int p,int l,int r){
	if(l<=t[p].l&&t[p].r<=r) return t[p];
	if(l>mid) return query(rs,l,r);//nl在中点右边 递归右区间 
	if(r<=mid) return query(ls,l,r);//nr在中点左边,递归左区间 <= ls
	else{//跨中间
		Node ans,a,b;
		a=query(ls,l,r);
		b=query(rs,l,r);
		ans.sum=a.sum+b.sum;
		ans.ans=max(max(a.ans,a.rans+b.lans),b.ans);
		ans.lans=max(a.lans,a.sum+b.lans);
		ans.rans=max(b.rans,b.sum+a.rans);
		return ans;
	}
}

int main(){
    int m;
	scanf("%d%d",&n,&m);
	build(1,1,n);
	int k,l,r;
	for(int i=0;ir) swap(l,r);
			printf("%d\n",query(1,l,r).ans);
		}else{
			update(1,l,r);
		}
	}
}

 

你可能感兴趣的:(数据结构-线段树)