Toocold之区间最大子段和

Toocold学会了怎样求区间最大子段和,现在他又玩出了新花样.他有n个数,他想知道对于区间的左端点l限定在[ll,rr]之间, 对于区间的右端点r限定在[ll2,rr2]之间的区间最大和是多少?

Input

输入第一行cas(1<=cas<=10)表示有几个cas

接下来每个cas的第一行是一个数n(1<=n<=100000)表示有n个数

第二行有n个数,a1,a2,a3...an(-1000<=ai<=1000)

第三行一个数q(1<=q<=100000)表示有q个询问

接下来q行每行四个数字ll, rr, ll2, rr2.(1<=ll,rr,ll2,rr2<=n)(ll<=rr)(ll2<=rr2)(rr2>=ll)
表示左端点l的范围和右端点r的范围

Output

每个询问输出符合范围的区间最大和

Sample Input

1
6
4 -3 1 -3 5 -2
2
1 4 2 5
1 1 3 4

Sample Output

4
2

Hint

div2(D)
#include<bits/stdc++.h>
using namespace std;
const int MAXN=100015;
int n,m;
int a[MAXN],pre_sum[MAXN],suf_sum[MAXN],l1,l2,r1,r2;
struct tnode
{
    int sum,lmax,rmax,ans;
	int l,r;
};
tnode operator + (const tnode& a,const tnode& b)
{
    tnode c;
    c.l=a.l;
    c.r=b.r;
    c.sum=a.sum+b.sum;
    c.lmax=max(a.lmax,a.sum+b.lmax);
    c.rmax=max(a.rmax+b.sum,b.rmax);
    c.ans=max(a.ans,b.ans);
    c.ans=max(c.ans,a.rmax+b.lmax);
    return c;
}
struct Segment_Tree
{
	tnode t[4*MAXN];
	void update(int root)
	{
	    int ch=root<<1;
	    t[root]=t[ch]+t[ch+1];
	}
	void buildt(int root,int l,int r,int A[])
	{
		if(l!=r)
		{
			int mid=(l+r)>>1;
			int ch=root<<1;
			buildt(ch,l,mid,A);
			buildt(ch+1,mid+1,r,A);
			update(root);
		}
		else
        {
            t[root].ans=t[root].lmax=t[root].rmax=t[root].sum=A[l];
            t[root].l=t[root].r=l;
        }
	}
	tnode query(int root,int l,int r)
	{
		if(t[root].l==l&&t[root].r==r)
		{
			return t[root];
		}
		int mid=(t[root].l+t[root].r)>>1;
		int ch=root<<1;
		if(r<=mid)return query(ch,l,r);
		else if(l>mid)return query(ch+1,l,r);
		else return query(ch,l,mid)+query(ch+1,mid+1,r);
	}
};
Segment_Tree ST1;
struct tnodes
{
    int Max;
	int l,r;
};
struct Segment_Tree_Max
{
	tnodes t[4*MAXN];
	void buildt(int root,int l,int r,int A[])
	{
		t[root].l=l;
		t[root].r=r;
		if(l!=r)
		{
			int mid=(l+r)>>1;
			int ch=root<<1;
			buildt(ch,l,mid,A);
			buildt(ch+1,mid+1,r,A);
			t[root].Max=max(t[ch].Max,t[ch+1].Max);
		}
		else t[root].Max=A[l];
	}
	int query(int root,int l,int r)
	{
		if(t[root].l==l&&t[root].r==r)
		{
			return t[root].Max;
		}
		int mid=(t[root].l+t[root].r)>>1;
		int ch=root<<1;
		if(r<=mid)return query(ch,l,r);
		else if(l>mid)return query(ch+1,l,r);
		else return max(query(ch,l,mid),query(ch+1,mid+1,r));
	}
};
Segment_Tree_Max ST2,ST3;
int get_sum(int l,int r)
{
    if(l>r)return 0;
    return pre_sum[r]-pre_sum[l-1];
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
        }
        ST1.buildt(1,1,n,a);
        pre_sum[0]=suf_sum[n+1]=0;
        for(int i=1;i<=n;++i)
        {
            pre_sum[i]=pre_sum[i-1]+a[i];
        }
        for(int i=n;i;--i)
        {
            suf_sum[i]=suf_sum[i+1]+a[i];
        }
        ST2.buildt(1,1,n,pre_sum);
        ST3.buildt(1,1,n,suf_sum);
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d %d %d %d",&l1,&r1,&l2,&r2);
            if(r1<l2)///3 无交
            {
                printf("%d\n",ST3.query(1,l1,r1)-pre_sum[n]+ST2.query(1,l2,r2));
            }
            else if(l2<=l1&&l1<=r2&&r2<=r1)///2
            {
                printf("%d\n",ST1.query(1,l1,r2).ans);
            }
            else if(l1<=l2&&l2<=r1&&r1<=r2)///1
            {
                int temp=ST1.query(1,l2,r1).ans;
                if(l2-1>=l1)
                {
                    temp=max(temp,ST3.query(1,l1,l2-1)-pre_sum[n]+ST2.query(1,l2,r2));
                }
                if(r1+1<=r2)
                {
                    temp=max(temp,ST2.query(1,r1+1,r2)-pre_sum[n]+ST3.query(1,l1,r1));
                }
                printf("%d\n",temp);
            }
            else if(l1<=l2&&l2<=r2&&r2<=r1)///4
            {
                int temp=ST1.query(1,l2,r2).ans;
                if(l2-1>=l1)
                {
                    temp=max(temp,ST3.query(1,l1,l2-1)-pre_sum[n]+ST2.query(1,l2,r2));
                }
                printf("%d\n",temp);
            }
            else if(l2<=l1&&l1<=r1&&r1<=r2)///5
            {
                int temp=ST1.query(1,l1,r1).ans;
                if(r1+1<=r2)
                {
                    temp=max(temp,ST2.query(1,r1+1,r2)-pre_sum[n]+ST3.query(1,l1,r1));
                }
                printf("%d\n",temp);
            }
        }
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
const long long MAXN=100015;
long long n,m;
long long a[MAXN],pre_sum[MAXN],suf_sum[MAXN],l1,l2,r1,r2;
struct tnode
{
    long long sum,lmax,rmax,ans;
	long long l,r;
};
tnode operator + (const tnode& a,const tnode& b)
{
    tnode c;
    c.l=a.l;
    c.r=b.r;
    c.sum=a.sum+b.sum;
    c.lmax=max(a.lmax,a.sum+b.lmax);
    c.rmax=max(a.rmax+b.sum,b.rmax);
    c.ans=max(a.ans,b.ans);
    c.ans=max(c.ans,a.rmax+b.lmax);
    return c;
}
struct Segment_Tree
{
	tnode t[4*MAXN];
	void update(long long root)
	{
	    long long ch=root<<1;
	    t[root]=t[ch]+t[ch+1];
	}
	void buildt(long long root,long long l,long long r,long long A[])
	{
		if(l!=r)
		{
			long long mid=(l+r)>>1;
			long long ch=root<<1;
			buildt(ch,l,mid,A);
			buildt(ch+1,mid+1,r,A);
			update(root);
		}
		else
        {
            t[root].ans=t[root].lmax=t[root].rmax=t[root].sum=A[l];
            t[root].l=t[root].r=l;
        }
	}
	tnode query(long long root,long long l,long long r)
	{
		if(t[root].l==l&&t[root].r==r)
		{
			return t[root];
		}
		long long mid=(t[root].l+t[root].r)>>1;
		long long ch=root<<1;
		if(r<=mid)return query(ch,l,r);
		else if(l>mid)return query(ch+1,l,r);
		else return query(ch,l,mid)+query(ch+1,mid+1,r);
	}
};
Segment_Tree ST1;
struct tnodes
{
    long long Max;
	long long l,r;
};
struct Segment_Tree_Max
{
	tnodes t[4*MAXN];
	void buildt(long long root,long long l,long long r,long long A[])
	{
		t[root].l=l;
		t[root].r=r;
		if(l!=r)
		{
			long long mid=(l+r)>>1;
			long long ch=root<<1;
			buildt(ch,l,mid,A);
			buildt(ch+1,mid+1,r,A);
			t[root].Max=max(t[ch].Max,t[ch+1].Max);
		}
		else t[root].Max=A[l];
	}
	long long query(long long root,long long l,long long r)
	{
		if(t[root].l==l&&t[root].r==r)
		{
			return t[root].Max;
		}
		long long mid=(t[root].l+t[root].r)>>1;
		long long ch=root<<1;
		if(r<=mid)return query(ch,l,r);
		else if(l>mid)return query(ch+1,l,r);
		else return max(query(ch,l,mid),query(ch+1,mid+1,r));
	}
};
Segment_Tree_Max ST2,ST3;
long long get_sum(long long l,long long r)
{
    if(l>r)return 0;
    return pre_sum[r]-pre_sum[l-1];
}
int main()
{
    long long T;
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        assert(n<=100000);
        for(long long i=1;i<=n;++i)
        {
            scanf("%lld",&a[i]);
            assert(-1000<=a[i]&&a[i]<=1000);
        }
        ST1.buildt(1,1,n,a);
        pre_sum[0]=suf_sum[n+1]=0;
        for(long long i=1;i<=n;++i)
        {
            pre_sum[i]=pre_sum[i-1]+a[i];
        }
        for(long long i=n;i;--i)
        {
            suf_sum[i]=suf_sum[i+1]+a[i];
        }
        ST2.buildt(1,1,n,pre_sum);
        ST3.buildt(1,1,n,suf_sum);
        scanf("%lld",&m);
        while(m--)
        {
            long long ans;
            scanf("%lld %lld %lld %lld",&l1,&r1,&l2,&r2);
            assert(l1<=r1);
            assert(l2<=r2);
            assert(r2>=l1);
            if(r1<l2)///3 无交
            {
                ans=ST3.query(1,l1,r1)-pre_sum[n]+ST2.query(1,l2,r2);
            }
            else if(l2<=l1&&l1<=r2&&r2<=r1)///2
            {
                ans=ST1.query(1,l1,r2).ans;
            }
            else if(l1<=l2&&l2<=r1&&r1<=r2)///1
            {
                long long temp=ST1.query(1,l2,r1).ans;
                if(l2-1>=l1)
                {
                    temp=max(temp,ST3.query(1,l1,l2-1)-pre_sum[n]+ST2.query(1,l2,r2));
                }
                if(r1+1<=r2)
                {
                    temp=max(temp,ST2.query(1,r1+1,r2)-pre_sum[n]+ST3.query(1,l1,r1));
                }
                ans=temp;
            }
            else if(l1<=l2&&l2<=r2&&r2<=r1)///4
            {
                long long temp=ST1.query(1,l2,r2).ans;
                if(l2-1>=l1)
                {
                    temp=max(temp,ST3.query(1,l1,l2-1)-pre_sum[n]+ST2.query(1,l2,r2));
                }
                ans=temp;
            }
            else if(l2<=l1&&l1<=r1&&r1<=r2)///5
            {
                long long temp=ST1.query(1,l1,r1).ans;
                if(r1+1<=r2)
                {
                    temp=max(temp,ST2.query(1,r1+1,r2)-pre_sum[n]+ST3.query(1,l1,r1));
                }
                ans=temp;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值