SPOJ GSS5 Can you answer these queries V

Can you answer these queries V

Time Limit: 1000ms
Memory Limit: 262144KB
This problem will be judged on  SPOJ. Original ID: GSS5
64-bit integer IO format: %lld      Java class name: Main

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+1]+...+A[j] ; x1 <= i <= y1 , x2 <= j <= y2 and x1 <= x2 , y1 <= y2 }. Given M queries (1 <= M <= 10000), your program must output the results of these queries.

Input

The first line of the input consist of the number of tests cases <= 5. Each case consist of the integer N and the sequence A. Then the integer M. M lines follow, contains 4 numbers x1, y1, x2 y2.

Output

Your program should output the results of the M queries for each test case, one query per line.

Example

Input:
2
6 3 -2 1 -4 5 2
2
1 1 2 3
1 3 2 5
1 1
1
1 1 1 1

Output:
2
3
1

解题:线段树,两个区间交与不交 讨论即可
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 100010;
 4 struct node{
 5     int lt,rt,lsum,rsum,sum,msum;
 6 }tree[maxn<<2];
 7 int A[maxn];
 8 inline void pushup(node &a,node &b,node &c){
 9     c.sum = a.sum + b.sum;
10     c.lsum = max(a.lsum,a.sum + b.lsum);
11     c.rsum = max(b.rsum,b.sum + a.rsum);
12     c.msum = max(max(a.msum,b.msum),a.rsum + b.lsum);
13 }
14 void build(int lt,int rt,int v){
15     tree[v].lt = lt;
16     tree[v].rt = rt;
17     if(lt == rt){
18         scanf("%d",&tree[v].sum);
19         tree[v].lsum = tree[v].rsum = tree[v].msum = tree[v].sum;
20         A[lt] = tree[v].sum;
21         return;
22     }
23     int mid = (lt + rt)>>1;
24     build(lt,mid,v<<1);
25     build(mid + 1,rt,v<<1|1);
26     pushup(tree[v<<1],tree[v<<1|1],tree[v]);
27 }
28 node query(int lt,int rt,int v){
29     if(lt > rt){
30         node tmp;
31         tmp.sum = tmp.lsum = tmp.rsum = tmp.msum = 0;
32         return tmp;
33     }
34     if(lt <= tree[v].lt && rt >= tree[v].rt) return tree[v];
35     if(rt <= tree[v<<1].rt) return query(lt,rt,v<<1);
36     if(lt >= tree[v<<1|1].lt) return query(lt,rt,v<<1|1);
37     node a = query(lt,rt,v<<1),b = query(lt,rt,v<<1|1),c;
38     pushup(a,b,c);
39     return c;
40 }
41 int main(){
42     int kase,n,m,x1,y1,x2,y2;
43     scanf("%d",&kase);
44     while(kase--){
45         scanf("%d",&n);
46         build(1,n,1);
47         scanf("%d",&m);
48         while(m--){
49             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
50             if(y1 < x2){
51                 int a = query(x1,y1,1).rsum;
52                 int b = query(x2,y2,1).lsum;
53                 int c = x2 - y1 > 1?query(y1+1,x2-1,1).sum:0;
54                 printf("%d\n",a + b + c);
55             }else{
56                 int a = query(x1,x2,1).rsum + query(x2,y1,1).lsum - A[x2];
57                 int b = query(x1,y1,1).rsum + query(y1,y2,1).lsum - A[y1];
58                 int c = query(x2,y1,1).msum;
59                 printf("%d\n",max(max(a,b),c));
60             }
61         }
62     }
63     return 0;
64 }
View Code

 

转载于:https://www.cnblogs.com/crackpotisback/p/4889858.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值