SPOJ GSS2 Can you answer these queries II

Time Limit: 1000MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu

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 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

Hint

Added by: Fudan University Problem Setters
Date: 2007-05-16
Time limit: 1s
Source limit: 50000B
Memory limit: 1536MB
Cluster: Cube (Intel G860)
Languages: All except: C99 strict ERL JS
Resource: Description, standard program and test data by Yang Zhe

这系列题没按难度顺序来啊……1~5里面感觉这道最难。

用线段树的叶子结点存a[i]表示序列的后缀和(即data[i]+data[i+1]+data[i+2]+...+data[n]),以及区间内最优答案。

离线处理,将询问按右端点从小到大排序。for i:=1 to n 从左往右不断将data[i]添加到线段树,并回答右端点等于i的询问(此时线段树里存的后缀和都只到i)。

如何排除重复数字?离散化数据,对每个数字记录上次出现的位置last,往线段树里添加新值时,只修改闭区间[last+1,i]

具体维护方法看代码:

  1 /*by SilverN*/
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<cmath>
  7 #define lc rt<<1
  8 #define rc rt<<1|1
  9 #define LL long long
 10 using namespace std;
 11 const int mxn=120010;
 12 int read(){
 13     int x=0,f=1;char ch=getchar();
 14     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
 15     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
 16     return x*f;
 17 }
 18 int n,m;
 19 int data[mxn];
 20 int last[mxn<<2];//离散化
 21 struct node{
 22     LL mx;//区间内最优解
 23     LL prelazy,mksum;//标记
 24     LL smm;//区间内最优的后缀和
 25 }t[mxn<<2],tmp0;
 26 void push_up(int l,int r,int rt){
 27     t[rt].mx=max(t[lc].mx,t[rc].mx);
 28     t[rt].smm=max(t[lc].smm,t[rc].smm);
 29     return;
 30 }
 31 void pushdown(int l,int r,int rt){
 32     if(!t[rt].mksum && !t[rt].prelazy)return;
 33     int ls=rt<<1;int rs=rt<<1|1;
 34     //L
 35     t[ls].prelazy=max(t[ls].prelazy,t[ls].mksum+t[rt].prelazy);
 36     t[ls].mx=max(t[ls].mx,t[ls].smm+t[rt].prelazy);
 37     t[ls].mksum+=t[rt].mksum;
 38     t[ls].smm+=t[rt].mksum;
 39     //R
 40     t[rs].prelazy=max(t[rs].prelazy,t[rs].mksum+t[rt].prelazy);
 41     t[rs].mx=max(t[rs].mx,t[rs].smm+t[rt].prelazy);
 42     t[rs].mksum+=t[rt].mksum;
 43     t[rs].smm+=t[rt].mksum;
 44     //
 45     t[rt].prelazy=t[rt].mksum=0;
 46     return;
 47 }
 48 void change(int L,int R,LL v,int l,int r,int rt){
 49     if(L<=l && r<=R){
 50         t[rt].smm+=v;//最优后缀和
 51         t[rt].mksum+=v;//后缀和的增加量
 52         t[rt].mx=max(t[rt].mx,t[rt].smm);//答案
 53         t[rt].prelazy=max(t[rt].prelazy,t[rt].mksum);//答案的增加量
 54         return;
 55     }
 56     int mid=(l+r)>>1;
 57     pushdown(l,r,rt);
 58     if(L<=mid)change(L,R,v,l,mid,lc);
 59     if(R>mid)change(L,R,v,mid+1,r,rc);
 60     push_up(l,r,rt);
 61     return;
 62 }
 63 LL query(int L,int R,int l,int r,int rt){
 64     if(L<=l && r<=R)return t[rt].mx;
 65     pushdown(l,r,rt);
 66     int mid=(l+r)>>1;
 67     LL res=-1e15;
 68     if(L<=mid)res=max(res,query(L,R,l,mid,lc));
 69     if(R>mid)res=max(res,query(L,R,mid+1,r,rc));
 70     return res;
 71 }
 72 struct qry{//存储询问
 73     int l,r,id;
 74 }q[mxn];
 75 int cmp(qry a,qry b){
 76     return a.r<b.r;//按右端点从小到大排序
 77 }
 78 LL ans[mxn];
 79 int bas=100001;
 80 int main(){
 81     n=read();
 82     int i,j,x,y,k;
 83     for(i=1;i<=n;i++)data[i]=read();
 84 //    Build(1,n,1);
 85     m=read();
 86     for(i=1;i<=m;i++){
 87         q[i].l=read();q[i].r=read();q[i].id=i;
 88     }
 89     sort(q+1,q+m+1,cmp);
 90     //
 91     int hd=1;//待处理询问
 92     for(i=1;i<=n;i++){
 93         change(last[data[i]+bas]+1,i,data[i],1,n,1);
 94         last[data[i]+bas]=i;
 95         while(hd<=m && q[hd].r==i){
 96             ans[q[hd].id]=query(q[hd].l,q[hd].r,1,n,1);
 97             hd++;
 98         }
 99     }
100     for(i=1;i<=m;i++)
101         printf("%lld\n",ans[i]);
102     return 0;
103 }
时间: 2024-09-30 14:16:16

SPOJ GSS2 Can you answer these queries II的相关文章

spoj gss2 : Can you answer these queries II 离线&amp;&amp;线段树

1557. Can you answer these queries II Problem code: GSS2 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 co

SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)

GSS2 - Can you answer these queries II #tree 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

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 1557 Can you answer these queries II 线段树 任意区间最大子段和 不重复数字

题目链接:点击打开链接 每个点都是最大值,把一整个序列和都压缩在一个点里. #include <vector> #include <iostream> #include <algorithm> #include <string.h> #include <stdio.h> using namespace std; #define N 100005 #define Lson(x) (x<<1) #define Rson(x) (x<

BZOJ2482: [Spoj1557] Can you answer these queries II

题解: 从没见过这么XXX的线段树啊... T_T 我们考虑离线做,按1-n一个一个插入,并且维护区间[ j,i](i为当前插入的数)j<i的最优值. 但这个最优值!!! 我们要保存历史的最优值,以及当前的最优值!!!还有lazy!!!也得分历史和现在!!T_T 怎么搞!!! inline void update(int k,int z1,int z2) { t[k].tag[1]=max(t[k].tag[1],t[k].tag[0]+z2); t[k].tag[0]+=z1; t[k].mx

SPOJ 1043 Can you answer these queries I 求任意区间最大连续子段和 线段树

题目链接:点击打开链接 维护区间左起连续的最大和,右起连续的和.. #include <cstdio> #include <iostream> #include <algorithm> #include <string.h> #include <math.h> #include <vector> #include <map> using namespace std; #define N 50050 #define Lson

SPOJ 4487. Can you answer these queries VI splay

题目链接:点击打开链接 题意比较明显,不赘述. 删除时可以把i-1转到根,把i+1转到根下 则i点就在 根右子树 的左子树,且只有i这一个 点 #include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; #define N 300500 #define inf 10000000 #define L(x) tree[x].ch[

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