2018.10.16 spoj Can you answer these queries V(线段树)

版权声明:随意转载哦......但还是请注明出处吧: https://blog.csdn.net/dreaming__ldx/article/details/83096465

传送门
线段树经典题。
就是让你求左端点在 [ l 1 , r 1 ] [l1,r1] 之间,右端点在 [ l 2 , r 2 ] [l2,r2] 之间且满足 l 1 l 2 , r 1 r 2 l1\le l2,r1 \le r2 的最大子段和。


直接分类讨论就行了。
如果两个区间不相交的话,答案就是 r m a x ( l 1 , l 2 ) + s u m ( l 2 + 1 , l 2 1 ) + l m a x ( l 2 , r 2 ) rmax(l1,l2)+sum(l2+1,l2-1)+lmax(l2,r2)
如果相交的话,讨论一下就是 m a x ( m a x ( r m a x ( l 1 , l 2 ) + l m a x ( l 2 , r 2 ) v a l [ l 2 ] , r m a x ( l 1 , r 1 ) + l m a x ( r 1 , r 2 ) v a l [ r 1 ] ) , m i d m a x ( l 2 , r 1 ) ) max(max(rmax(l1,l2)+lmax(l2,r2)-val[l2],rmax(l1,r1)+lmax(r1,r2)-val[r1]),midmax(l2,r1))

代码:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define N 10005
using namespace std;
inline int read(){
	int ans=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans*w;
}
int n,m,a[N],T_T;
struct Node{int l,r,ls,rs,ms,sum;}T[N<<2];
inline Node operator+(const Node&a,const Node&b){
	Node ret;
	ret.l=a.l,ret.r=b.r,ret.sum=a.sum+b.sum;
	ret.ls=max(a.ls,a.sum+b.ls);
	ret.rs=max(b.rs,b.sum+a.rs);
	ret.ms=max(max(a.ms,b.ms),a.rs+b.ls);
	return ret;
}
inline void build(int p,int l,int r){
	T[p].l=l,T[p].r=r;
	if(l==r){T[p].ls=T[p].rs=T[p].ms=T[p].sum=a[l];return;}
	build(lc,l,mid),build(rc,mid+1,r),T[p]=T[lc]+T[rc];
}
inline Node query(int p,int ql,int qr){
	if(ql>T[p].r||qr<T[p].l)return (Node){T[p].l,T[p].r,0,0,0,0};
	if(ql<=T[p].l&&T[p].r<=qr)return T[p];
	if(qr<=mid)return query(lc,ql,qr);
	if(ql>mid)return query(rc,ql,qr);
	return query(lc,ql,mid)+query(rc,mid+1,qr);
}
int main(){
	T_T=read();
	while(T_T--){
		n=read();
		for(int i=1;i<=n;++i)a[i]=read();
		build(1,1,n),m=read();
		while(m--){
			int l1=read(),r1=read(),l2=read(),r2=read();
			if(r1<l2){
				Node ansl=query(1,l1,r1),ansm=query(1,r1+1,l2-1),ansr=query(1,l2,r2);
				printf("%d\n",ansl.rs+ansm.sum+ansr.ls);
			}
			else{
				int ans=query(1,l2,r1).ms;
				if(l1<l2)ans=max(ans,query(1,l1,l2).rs+query(1,l2,r2).ls-a[l2]);
				if(r2>r1)ans=max(ans,query(1,l1,r1).rs+query(1,r1,r2).ls-a[r1]);
				printf("%d\n",ans);
			}
		}
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/dreaming__ldx/article/details/83096465