SPOJ GSS5 Can you answer these queries V ——线段树

【题目分析】

GSS1上增加区间左右端点的限制。

直接分类讨论就好了。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 500005
#define eps 1e-8
#define db double
#define ll long long
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    #endif
}

int Getint()
{
    int x=0,f=1; char 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 Node{
	int lx,rx,mx,sum;
	Node operator + (Node x)
	{
		Node ret;
		ret.lx=max(lx,sum+x.lx);
		ret.rx=max(x.sum+rx,x.rx);
		ret.sum=sum+x.sum;
		ret.mx=max(max(mx,x.mx),max(rx+x.lx,max(ret.lx,ret.rx)));
		return ret;
	}
}t[maxn];

int n,a[maxn],q,L,R;

void Build(int o,int l,int r)
{
//	printf("Build %d %d\n",l,r);
	if (l==r)
	{
		t[o].lx=t[o].rx=t[o].mx=t[o].sum=a[l];
		return ;
	}
	int mid=l+r>>1;
	Build(o<<1,l,mid);
	Build(o<<1|1,mid+1,r);
	t[o]=t[o<<1]+t[o<<1|1];
}

Node Query(int o,int l,int r)
{
//	printf("Query %d %d\n",l,r);
	if (L<=l&&r<=R) return t[o];
	int mid=l+r>>1;
	if (L>mid) return Query(o<<1|1,mid+1,r);
	else if (R<=mid) return Query(o<<1,l,mid);
	else return Query(o<<1,l,mid)+Query(o<<1|1,mid+1,r);
}

int main()
{
	int T;
	Finout();scanf("%d",&T);
	while (T--)
	{
		memset(a,0,sizeof a);
		memset(t,0,sizeof t);
		scanf("%d",&n);
		F(i,1,n) scanf("%d",&a[i]);
		Build(1,1,n);
		scanf("%d",&q);
		F(i,1,q)
		{
			int x1=Getint(),y1=Getint(),x2=Getint(),y2=Getint(),ans=0;
			if (x2>y1)
			{
				L=x1;R=y1; ans+=Query(1,1,n).rx;// printf("ans 1: %d\n",ans);
				L=x2;R=y2; ans+=Query(1,1,n).lx; //printf("ans 2: %d\n",ans);
				L=y1+1;R=x2-1; if (R>=L) ans+=Query(1,1,n).sum;//printf("ans 3: %d\n",ans);
			}
			else
			{
				int tmp=0;
				L=x2;R=y1; ans=Query(1,1,n).mx;
				if (x2>x1)
				{L=x1;R=x2-1;tmp+=Query(1,1,n).rx;}
				L=x2;R=y2; tmp+=Query(1,1,n).lx;
				ans=max(ans,tmp); tmp=0;
				L=x2;R=y1; tmp+=Query(1,1,n).rx;
				if (y2>y1)
				{L=y1+1;R=y2;tmp+=Query(1,1,n).lx;}
				ans=max(ans,tmp);
			}
			printf("%d\n",ans);
		}
	}
}

  

时间: 2024-10-10 07:46:27

SPOJ GSS5 Can you answer these queries V ——线段树的相关文章

Spoj 2916 Can you answer these queries V 线段树 求任意重叠区间的最大子段和

题目链接:点击打开链接 题意: T个测试数据 n个数字 q个询问 每个询问 : [x1, y1] [x2, y2] 问: int ans = -inf; for(int i = x1; i <= y1; i++) for(int j = max(x2, i); j <= y2; j++) ans = max(ans, query(i, j)); 思路: query_L(int l, int r) 求的是在区间[l,r]内 ,左端点为l的最大子段和. 其他和GSS3差不多. 分类讨论一下给定的区

SPOJ GSS5 Can you answer these queries V (线段树)

原来有一两个人说我不帅的时候,我不以为意,逗我玩而已,后来几乎所有 人都说我不帅,我才真正意识到事态的严重,这社会骗子真是越来越多了... 好吧我承认,这个笑话不好笑,其实我想说的是,做人一定要坚持自己的原则, 哪怕有一天所有人都和你背道而驰,都不要放弃自己当初的梦想,如果有一天, 我们淹没在人海之中,庸碌一生,那是因为我们不够努力,不够勇敢的去面对生活. 每天积累一点点,嗯,满足简单的快乐. ---------------------------------------------------

SPOJ GSS3 Can you answer these queries III (线段树)

题目大意: 求区间最大子区间的和. 思路分析: 记录左最大,右最大,区间最大. 注意Q_L  和 Q_R  就好. #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define lson num<<1,s,mid #define rson num<<1|1,mid+1,e #define maxn 55555 using na

SPOJ GSS4 Can you answer these queries IV (线段树)

题目大意: 给出N个数 0     操作   把 l -----  r之间的数全部开平方 1     操作  输出 l -----r  之间的和 思路分析: 判断区间里的数字是否全相同.如果相同, 将cov 置为该数 查询的时候和更新的时候,如果碰到cov != -1 的  就直接返回就可以了 #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #incl

SPOJ GSS5 Can you answer these queries V

Time Limit: 132MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description You are given a sequence A[1], A[2], ..., A[N] . ( |A[i]| <= 10000 , 1 <= N <= 10000 ). A query is defined as follows: Query(x1,y1,x2,y2) = Max { A[i]+A[i+

bzoj 2482: [Spoj GSS2] Can you answer these queries II 线段树

2482: [Spoj1557] Can you answer these queries II Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 145  Solved: 76[Submit][Status][Discuss] Description 给定n个元素的序列. 给出m个询问:求l[i]~r[i]的最大子段和(可选空子段). 这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次. 比如:1,2,3,2,2,2出现了3次,但只算一次,

SPOJ 1557. Can you answer these queries II 线段树

Can you answer these queries II Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 https://www.spoj.com/problems/GSS2/ Description Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse

SPOJ GSS3 Can you answer these queries III ——线段树

[题目分析] GSS1的基础上增加修改操作. 同理线段树即可,多写一个函数就好了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream&

Spoj 1716 Can you answer these queries III 线段树 单点修改 区间求最大子段和

题目链接:点击打开链接 == 原来写1的时候已经把更新函数写好了.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lso