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