zsyzlzy

导航

 

线段树裸题.

描述
给定长度为N的数列A,以及M条指令 (N≤500000, M≤100000),每条指令可能是以下两种之一:
“2 x y”,把 A[x] 改成 y。
“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 max(x≤l≤r≤y)⁡ { ∑(i=l~r) A[i] }。
对于每个询问,输出一个整数表示答案。

输入格式
第一行两个整数N,M

第二行N个整数Ai

接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改

输出格式
对于每个询问输出一个整数表示答案。

样例输入
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 3 2
样例输出
2
-1
数据范围与约定
对于100%的数据: N≤500000, M≤100000, |Ai|<=1000

线段树只需维护4个参数,ls,rs,res,sls,rs,res,s,分别表示区间从左起最大和,区间从右起最大和,区间最大连续子段和,区间和.

维护函数:

inline void upd(int x) {
	s[x]=s[lc]+s[rc];
	ls[x]=max(ls[lc],s[lc]+ls[rc]);
	rs[x]=max(rs[rc],s[rc]+rs[lc]);
	res[x]=max(max(res[lc],res[rc]),rs[lc]+ls[rc]);
}

查询的时候用两个变量:ans,tmpans,tmp即可.
tmptmp表示右端点为当前线段树区间左端点-1的最大连续子段和.

代码:

#include<cstdio>
#include<cctype>
#include<cstring>
#define g getchar()
#define lc (x<<1)
#define rc (x<<1|1)
#define max(x,y) (x>y?x:y)
using namespace std;
typedef long long ll;
const int N=1<<19;
const ll inf=1LL<<63;
template<class o>
inline void qr(o&x) {
	char c=g;x=0;int f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=g;}
	while(isdigit(c))x=x*10+c-'0',c=g;
	x*=f;
}
void write(ll x) {
	if(x/10)write(x/10);
	putchar(x%10+'0');
}
void pri(ll x) {
	if(x<0)putchar('-'),x=-x;
	write(x);puts("");
}

template<typename o>
inline void swap(o&x,o&y) { o t=x;x=y;y=t;}
ll res[N<<1],ls[N<<1],rs[N<<1],s[N<<1];
inline void upd(int x) {
	s[x]=s[lc]+s[rc];
	ls[x]=max(ls[lc],s[lc]+ls[rc]);
	rs[x]=max(rs[rc],s[rc]+rs[lc]);
	res[x]=max(max(res[lc],res[rc]),rs[lc]+ls[rc]);
}
void bt(int x,int l,int r) {
	if(l==r){qr(s[x]);ls[x]=rs[x]=res[x]=s[x];return ;}
	int mid=(l+r)>>1;
	bt(lc,l,mid);
	bt(rc,mid+1,r);
	upd(x);
}
void change(int x,int l,int r,const int &pos,const ll &d) {
	if(l==r){ls[x]=rs[x]=res[x]=s[x]=d;return ;}
	int mid=(l+r)>>1;
	if(pos<=mid)change(lc,l,mid,pos,d);
	else 		change(rc,mid+1,r,pos,d);
	upd(x);
}
ll ans,tmp;
void query(int x,int l,int r,const int &L,const int &R) {
	if(L<=l&&r<=R) {
		ans=max(ans,max(res[x],tmp+ls[x]));
		tmp=max(tmp+s[x],max(rs[x],0LL));
		return ;
	}
	int mid=(l+r)>>1;
	if(L<=mid)query(lc,l,mid,L,R);
	if(mid< R)query(rc,mid+1,r,L,R);
}
int main() {
	register int n,m;qr(n);qr(m);bt(1,1,n);
	int op;ll l,r;
	while(m--) {
		qr(op),qr(l);qr(r);
		switch(op) {
			case 1:
				if(l>r)swap(l,r);
				ans=inf;tmp=0;
				query(1,1,n,l,r);
				pri(ans);break;
			case 2:
				change(1,1,n,l,r);
				break;
			}
	}
	return 0;
}
posted on 2019-10-12 21:35  zsyzlzy  阅读(104)  评论(0编辑  收藏  举报