【树形结构】训练题E - Can you answer these queries V

题意

同样是求字段最大和 不过要求是i在[x1,y1]之间,j在[x2,y2]之间。

思路

首先是两大类情况讨论

一、y1<x2

二、y1>=x2

其次就是一些缩短时间的方法:快读,规避掉数组读入,使用位运算,在每个函数结束后加上return(日常tle太难受了)

代码

#include<iostream>
#include<cmath>
#include<stack>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>

#define Endl "\n"
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
using namespace std;

inline ll read(){
	ll x = 0, f = 1; char ch; ch = getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
struct segmentTree{
	int lmax,rmax,sum,dat;
}tr[maxn<<2];

int a[maxn];

void up(int p){
	int ll=p<<1; int rr=ll|1;
	tr[p].sum=tr[ll].sum+tr[rr].sum;
	tr[p].lmax=max(tr[ll].lmax,tr[ll].sum+tr[rr].lmax);
	tr[p].rmax=max(tr[rr].rmax,tr[rr].sum+tr[ll].rmax);
	tr[p].dat=max(max(tr[ll].dat,tr[rr].dat),tr[ll].rmax+tr[rr].lmax);
	return ;
}
void build(int p,int l,int r){
	if(l==r){
		tr[p].dat=tr[p].sum=tr[p].lmax=tr[p].rmax=read();
		return ;
	}
	int mid=(l+r)>>1;
	int ll=p<<1;
	int rr=ll|1;
	build(ll,l,mid);
	build(rr,mid+1,r);
	up(p);
}
segmentTree query(int p,int l,int r,int ql,int qr){
	if(ql<=l&&qr>=r)
		return tr[p];
	int mid=(l+r)>>1;
	int ll=p<<1;
	int rr=ll|1;
	if(ql>mid)
		return query(rr,mid+1,r,ql,qr);
	else if(qr<=mid)
		return query(ll,l,mid,ql,qr);
	else{
		segmentTree ans,a,b;
		a=query(ll,l,mid,ql,qr);
		b=query(rr,mid+1,r,ql,qr);
		ans.sum=a.sum+b.sum;
		ans.dat=max(a.dat,a.rmax+b.lmax);
		ans.dat=max(ans.dat,b.dat);
		ans.lmax=max(a.lmax,a.sum+b.lmax);
		ans.rmax=max(b.rmax,b.sum+a.rmax);
		return ans;
	}
}
ll t,m,res=0;
int x1,y11,x2,y2;
int main()
{

	t=read();
	while(t--)
	{
		int n;
		n=read();
		build(1,1,n);
		m=read();
		while(m--)
		{
			x1=read(),y11=read(),x2=read(),y2=read();
			if(y11<x2)
			{
				res=query(1,1,n,y11,x2).sum;
				if(x1 < y11)res+=max(0,query(1,1,n,x1,y11-1).rmax);
				if(x2 < y2)	res+=max(0,query(1,1,n,x2+1,y2).lmax);
			}
			else
			{
				ll res1 = query(1,1,n,x1,x2).rmax;
				if(x2<y2)	res1+=max(0,query(1,1,n,x2+1,y2).lmax);
				
				ll res2=query(1,1,n,x2,y11).dat;
				
				ll res3 = query(1,1,n,x2,y11).rmax;
				if(y11<y2) res3+=max(0,query(1,1,n,y11+1,y2).lmax);
				
				 res=max(max(res1,res2),res3);
				
			//	cout<<"here 2 "<<res<<Endl;
			}
			
			cout<<res<<Endl;
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值