Link
SP1557 GSS2 - Can you answer these queries II
Solve
正向处理很难,我们思考离线处理,每次加入A[i]离线统计答案,所以这个时候线段树上的一个节点(l)就表示([l,A[i]])这个区间的答案。
这里x义x神仙已经将的很清楚了,补充一下,他用一个点来维护一段区间,是一种比较经典的做法。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int N,M;
int A[100005];
int pre[2000005];
struct node{
ll Max,HisMax,Lzy,HisLzy;
node operator +(const node b)const{
node c;c.Max=max(Max,b.Max);c.HisMax=max(HisMax,b.HisMax);
c.HisLzy=c.Lzy=0;
return c;
}
}K[400005];
void push_down(int x){
K[x<<1].HisMax=max(K[x<<1].HisMax,K[x<<1].Max+K[x].HisLzy);
K[x<<1].HisLzy=max(K[x<<1].HisLzy,K[x<<1].Lzy+K[x].HisLzy);
K[x<<1].Max+=K[x].Lzy;
K[x<<1].Lzy+=K[x].Lzy;
K[x<<1|1].HisMax=max(K[x<<1|1].HisMax,K[x<<1|1].Max+K[x].HisLzy);
K[x<<1|1].HisLzy=max(K[x<<1|1].HisLzy,K[x<<1|1].Lzy+K[x].HisLzy);
K[x<<1|1].Max+=K[x].Lzy;
K[x<<1|1].Lzy+=K[x].Lzy;
K[x].Lzy=K[x].HisLzy=0;
}
void Update(int x,int l,int r,int L,int R,ll k){
if(L<=l&&r<=R){
K[x].Max+=k;K[x].HisMax=max(K[x].HisMax,K[x].Max);
K[x].Lzy+=k;K[x].HisLzy=max(K[x].HisLzy,K[x].Lzy);
return;
}
push_down(x);
int mid=(l+r)>>1;
if(L<=mid) Update(x<<1,l,mid,L,R,k);
if(R>mid) Update(x<<1|1,mid+1,r,L,R,k);
K[x]=K[x<<1]+K[x<<1|1];
return;
}
node Query(int x,int l,int r,int L,int R){
if(L<=l&&r<=R) return K[x];
push_down(x);
int mid=(l+r)>>1;
if(R<=mid) return Query(x<<1,l,mid,L,R);
if(L>mid) return Query(x<<1|1,mid+1,r,L,R);
return Query(x<<1,l,mid,L,R)+Query(x<<1|1,mid+1,r,L,R);
}
int L[100005],R[100005],id[100005];
node Ans[100005];
bool cmp(int a,int b){
return R[a]<R[b];
}
int main(){
scanf("%d",&N);
for(int i=1;i<=N;i++) scanf("%d",&A[i]);
scanf("%d",&M);
for(int i=1;i<=M;i++) scanf("%d%d",&L[i],&R[i]),id[i]=i;
sort(id+1,id+M+1,cmp);
int j=1;
for(int i=1;i<=N;i++){
Update(1,1,N,pre[A[i]+100000]+1,i,A[i]);
pre[A[i]+100000]=i;
while(R[id[j]]==i&&j<=M) Ans[id[j]]=Query(1,1,N,L[id[j]],R[id[j]]),j++;
}
for(int i=1;i<=M;i++) printf("%lld
",Ans[i].HisMax);
return 0;
}