Can you answer these queries II

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

Being a completist and a simplist, kid Yang Zhe cannot solve but get Wrong Answer from most of the OI problems. And he refuse to write two program of same kind at all. So he always failes in contests.

When having a contest, Yang Zhe looks at the score of every problems first. For the problems of the same score, Yang Zhe will do only one of them. If he's lucky enough, he can get all the scores wanted.

Amber is going to hold a contest in SPOJ. She has made a list of N candidate problems, which fit Yang Zhe very well. So Yang Zhe can solve any problem he want. Amber lined up the problems, began to select. She will select a subsequence of the list as the final problems. Being A girl of great compassion, she'd like to select such a subsequence (can be empty) that Yang Zhe will get the maximal score over all the possible subsequences.

Amber found the subsequence easily after a few minutes. To make things harder, Amber decided that, Yang Zhe can take this contest only if Yang Zhe can answer her Q questions. The question is: if the final problems are limited to be a subsequence of list[X..Y] (1 <= X <= Y <= N), what's the maximal possible score Yang Zhe can get?

As we know, Yang Zhe is a bit idiot (so why did he solve the problem with a negative score?), he got Wrong Answer again... Tell him the correct answer!

Input

  • Line 1: integer N (1 <= N <= 100000);
  • Line 2: N integers denoting the score of each problem, each of them is a integer in range [-100000, 100000];
  • Line 3: integer Q (1 <= Q <= 100000);
  • Line 3+i (1 <= i <= Q): two integers X and Y denoting the ith question.

Output

  • Line i: a single integer, the answer to the ith question.

Example

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

Output:
4
5
3

Warning: large input/output data,be careful with certain languages
 

Source

 
解题:非常尤其特别厉害的线段树
假设没有重复的数据,那么

$s[1] = a[1] + a[2] + a[3] + ... + a[i];$
$s[2] = a[2] + a[3] + ... + a[i];$

$s[3] = a[3] + ... + a[i];$

$s[i] = a[i];$

也就是说,线段树上的每个叶子代表的是s[x]

我们说假设这个是后缀和,但是,我们要前缀和,所以在做lazy标记的时间做了手脚,只把最大的lazy下传去修改最大子段和

$ss[1] = max( a[1] + a[2]  + ... + a[k_1] ) (    k_1\leq i );$

$ss[2] = max( a[2] + a[3] + ...+ a[k_2] )  (    k_2\leq i );$

我们可以求的是以i为右端点的询问,就是 $ss[l] ....ss[r]( r == i )$ 中的最大值;

这样子就是维护了前缀和,既有前缀和,也有后缀和,答案自然就出来了

问题是有重复的怎么办?只要记录每个元素上次出现位置,然后把上次出现的位置+1到当前位置这一段加上当前元素就是了,这样保证每个s[i]里面最多只加入了该元素一次

 

SPOJ GSS2 Can you answer these queries II_后缀SPOJ GSS2 Can you answer these queries II_前缀和_02
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int maxn = 100010;
 5 struct node{
 6     int lt,rt;
 7     LL lazy,sum,maxlazy,maxsum;
 8 }tree[maxn<<2];
 9 struct QU{
10     int x,y,id;
11     bool operator<(const QU &rhs)const{
12         return y < rhs.y;
13     }
14 }q[maxn];
15 void build(int lt,int rt,int v){
16     tree[v].lt = lt;
17     tree[v].rt = rt;
18     tree[v].sum = tree[v].maxsum = 0;
19     tree[v].lazy = tree[v].maxlazy = 0;
20     if(lt == rt) return;
21     int mid = (lt + rt)>>1;
22     build(lt,mid,v<<1);
23     build(mid + 1,rt,v<<1|1);
24 }
25 void _set(int x,int y){
26     tree[x].maxlazy = max(tree[x].maxlazy,tree[x].lazy + tree[y].lazy);
27     tree[x].maxsum = max(tree[x].maxsum,tree[x].sum + tree[x].maxlazy);
28     tree[x].lazy += tree[y].lazy;
29     tree[x].sum += tree[x].lazy;
30 }
31 void pushdown(int v){
32     if(tree[v].lazy || tree[v].maxlazy){
33         _set(v<<1,v);
34         _set(v<<1|1,v);
35         tree[v].lazy = tree[v].maxlazy = 0;
36     }
37 }
38 void pushup(int v){
39     tree[v].sum = max(tree[v<<1].sum,tree[v<<1|1].sum);
40     tree[v].maxsum = max(tree[v<<1].maxsum,tree[v<<1|1].maxsum);
41 }
42 void update(int lt,int rt,int val,int v){
43     if(lt <= tree[v].lt && rt >= tree[v].rt){
44         tree[v].lazy += val;
45         tree[v].sum += val;
46         tree[v].maxlazy = max(tree[v].maxlazy,tree[v].lazy);
47         tree[v].maxsum = max(tree[v].maxsum,tree[v].sum);
48         return;
49     }
50     pushdown(v);
51     if(lt <= tree[v<<1].rt) update(lt,rt,val,v<<1);
52     if(rt >= tree[v<<1|1].lt) update(lt,rt,val,v<<1|1);
53     pushup(v);
54 }
55 LL query(int lt,int rt,int v){
56     if(lt <= tree[v].lt && rt >= tree[v].rt) return tree[v].maxsum;
57     pushdown(v);
58     if(rt <= tree[v<<1].rt) return query(lt,rt,v<<1);
59     if(lt >= tree[v<<1|1].lt) return query(lt,rt,v<<1|1);
60     return max(query(lt,rt,v<<1),query(lt,rt,v<<1|1));
61 }
62 int pre[maxn<<2],a[maxn],n,m;
63 LL ans[maxn];
64 int main(){
65     while(~scanf("%d",&n)){
66         memset(pre,0,sizeof pre);
67         for(int i = 1; i <= n; ++i)
68             scanf("%d",a + i);
69         scanf("%d",&m);
70         for(int i = 0; i < m; ++i){
71             scanf("%d%d",&q[i].x,&q[i].y);
72             q[i].id = i;
73         }
74         sort(q,q + m);
75         build(1,n,1);
76         for(int i = 1,j = 0; i <= n; ++i){
77             update(pre[a[i] + maxn] + 1,i,a[i],1);
78             pre[a[i] + maxn] = i;
79             while(j < m && q[j].y == i){
80                 ans[q[j].id] = max(0LL,query(q[j].x,q[j].y,1));
81                 ++j;
82             }
83         }
84         for(int i = 0; i < m; ++i) printf("%lld\n",ans[i]);
85     }
86     return 0;
87 }
View Code

 

夜空中最亮的星,照亮我前行