Description
给定n个元素的序列。
给出m个询问:求l[i]~r[i]的最大子段和(可选空子段)。
这个最大子段和有点特殊:一个数字在一段中出现了两次只算一次。
比如:1,2,3,2,2,2出现了3次,但只算一次,于是这个序列的和是1+2+3=6。
Input
第一行一个数n。
第二行n个数,为给定的序列,这些数的绝对值小于等于100000。
第三行一个数m。
接下来m行,每行两个数,l[i],r[i]。
Output
M行,每行一个数,为每个询问的答案。
Sample Input
9
4 -2 -2 3 -1 -4 2 2 -6
3
1 2
1 5
4 9
4 -2 -2 3 -1 -4 2 2 -6
3
1 2
1 5
4 9
Sample Output
4
5
3
HINT
【数据说明】
30%:1 <= n, m <= 100
100%:1 <= n, m <= 100000
Source
枚举右端点。我们用线段树维护以这个点开始到当前点的ans和过去最大ans
然后离线回答询问即可
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct tree
{
int l,r;
long long m,vm;
long long tag,vtag;
}tr[800001];
struct que
{
int l,r;
int p;
long long ans;
}ask[100001];
inline bool cmp1(que x,que y)
{
if(x.r<y.r)
return true;
return false;
}
inline bool cmp2(que x,que y)
{
if(x.p<y.p)
return true;
return false;
}
inline void up(int p)
{
tr[p].m=max(tr[p*2].m,tr[p*2+1].m);
tr[p].vm=max(tr[p*2].vm,tr[p*2+1].vm);
}
inline void push(int p)
{
tr[p*2].vm=max(tr[p*2].vm,tr[p*2].m+tr[p].vtag);
tr[p*2+1].vm=max(tr[p*2+1].vm,tr[p*2+1].m+tr[p].vtag);
tr[p*2].m+=tr[p].tag;
tr[p*2+1].m+=tr[p].tag;
tr[p*2].vtag=max(tr[p*2].vtag,tr[p*2].tag+tr[p].vtag);
tr[p*2+1].vtag=max(tr[p*2+1].vtag,tr[p*2+1].tag+tr[p].vtag);
tr[p*2].tag+=tr[p].tag;
tr[p*2+1].tag+=tr[p].tag;
tr[p].tag=0;
tr[p].vtag=0;
}
inline void build(int p,int l,int r)
{
tr[p].l=l;
tr[p].r=r;
if(l!=r)
{
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
up(p);
}
}
inline void add(int p,int l,int r,long long x)
{
if(l>r)
return ;
/* if(l==0)
l=1;*/
if(l<=tr[p].l&&tr[p].r<=r)
{
tr[p].m+=x;
tr[p].tag+=x;
tr[p].vm=max(tr[p].vm,tr[p].m);
tr[p].vtag=max(tr[p].vtag,tr[p].tag);
}
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
if(l<=mid)
add(p*2,l,r,x);
if(r>mid)
add(p*2+1,l,r,x);
up(p);
}
}
inline long long askx(int p,int l,int r)
{
if(l<=tr[p].l&&tr[p].r<=r)
return tr[p].vm;
else
{
push(p);
int mid=(tr[p].l+tr[p].r)/2;
long long ans=0;
if(l<=mid)
ans=max(ans,askx(p*2,l,r));
if(r>mid)
ans=max(ans,askx(p*2+1,l,r));
return ans;
}
}
int a[1000001];
int pre[1000001],la[1000001];
int main()
{
// freopen("sequence.in","r",stdin);
// freopen("sequence.out","w",stdout);
int n;
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
{
pre[i]=la[a[i]];
la[a[i]]=i;
}
build(1,1,n);
int m;
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&ask[i].l,&ask[i].r);
ask[i].p=i;
}
sort(ask+1,ask+1+m,cmp1);
int d=1;
for(i=1;i<=n;i++)
{
add(1,pre[i]+1,i,a[i]);
while(d<=m&&ask[d].r==i)
{
ask[d].ans=askx(1,ask[d].l,ask[d].r);
d++;
}
}
sort(ask+1,ask+1+m,cmp2);
for(i=1;i<=m;i++)
printf("%lld\n",ask[i].ans);
return 0;
}