vijos1083 小白逛公园

题目
题意:求区间最大连续子段和,有单点修改

Solution

s u m sum 表示区间和,
l l 表示包含左端点的最大连续子段和,
r r 表示包含右端点的最大连续子段和,
a l l all 表示整个区间的最大连续子段和

#include<bits/stdc++.h>
using namespace std;
const int N=500002;
#define mid ((l+r)>>1)
struct node{
	int sum,l,r,all;
}tr[N<<2];
int n,m,x,y,op;
inline char gc(){
	static char buf[100000],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int rd(){
	int x=0,fl=1;char ch=gc();
	for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
	for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
	return x*fl;
}
inline void wri(int a){if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){if(a<0)a=-a,putchar('-');wri(a),puts("");}
node operator +(node le,node ri){
	return (node){le.sum+ri.sum,max(le.l,le.sum+ri.l),max(ri.r,le.r+ri.sum),max(max(le.all,ri.all),le.r+ri.l)};
}
void build(int t,int l,int r){
	if (l==r){
		x=rd();
		tr[t]=(node){x,x,x,x};
		return;
	}
	build(t<<1,l,mid);
	build(t<<1|1,mid+1,r);
	tr[t]=tr[t<<1]+tr[t<<1|1];
}
node query(int t,int l,int r,int x,int y){
	if (x==l && r==y) return tr[t];
	if (y<=mid) return query(t<<1,l,mid,x,y);
	if (x>mid) return query(t<<1|1,mid+1,r,x,y);
	return query(t<<1,l,mid,x,mid)+query(t<<1|1,mid+1,r,mid+1,y);
}
void update(int t,int l,int r,int x,int v){
	if (l==r){
		tr[t]=(node){v,v,v,v};
		return;
	}
	if (x<=mid) update(t<<1,l,mid,x,y);
	else update(t<<1|1,mid+1,r,x,y);
	tr[t]=tr[t<<1]+tr[t<<1|1];
}
int main(){
	n=rd(),m=rd();
	build(1,1,n);
	for (;m--;){
		op=rd(),x=rd(),y=rd();
		if (op==1) wln(query(1,1,n,min(x,y),max(x,y)).all);
		else update(1,1,n,x,y);
	}
}

猜你喜欢

转载自blog.csdn.net/xumingyang0/article/details/84989664