SP1557 GSS2 - Can you answer these queries II
\(\bigstar\texttt{Hint}\):遇到去重的问题,我们通常考虑离线询问后处理。
可以枚举右端点,将询问存储在右端点,考虑用数据结构记录左端点的信息。
那么我们如果用线段树维护左端点为它时的答案,需要维护一下几种信息:
- 历史最大值 \(hismax\),
- 下传标记的增加值 \(lazadd\),
- 当前的区间最大值 \(maxx\),
WA 了捏,啊标记没有及时下传,可能有中间过程中的最大值没有统计到。
那就再记下一个 tag 表示历史最大 \(lazaddmax\) 对 \(lazadd\) 取最大值。
#define Maxn 400005
int n,m;
int a[Maxn],pre[Maxn<<1];
ll ans[Maxn];
vector<pa> q[Maxn];
/*
由于下面标价下传时变量名称容易引起误导,下次写的时候不妨这样写:
struct TREE
{// All=pushed+unpushedll maxAll,All,maxUnpused,UnpushedTREE(int _maxAll=0,int _All=0,int _maxUnpushed=0,int _Unpushed=0):maxAll(_maxAll),All(_All),maxUnpushed(_maxUnpushed),Unpushed(_Unpushed){}inline void Push(ll New,ll maxNew){maxAll=max(maxAll,All+maxNew);All+=New;maxUnpushed=max(maxUnpushed,maxNew);Unpushed+=New;}
}tree[Maxn<<2];
*/
struct TREE
{ll hismax,lazadd,maxx,lazaddmax;TREE(int H=0,int La=0,int M=0,int Lam=0):hismax(H),lazadd(La),maxx(M),lazaddmax(Lam){}inline void Push(ll x,ll addmax){lazaddmax=max(lazaddmax,lazadd+addmax);lazadd+=x;hismax=max(hismax,maxx+addmax);maxx+=x;}
}tree[Maxn<<2];
inline void pushdown(int p)
{tree[p<<1].Push(tree[p].lazadd,tree[p].lazaddmax);tree[p<<1|1].Push(tree[p].lazadd,tree[p].lazaddmax);tree[p].lazadd=tree[p].lazaddmax=0;
}
inline void pushup(int p)
{tree[p].maxx=max(tree[p<<1].maxx,tree[p<<1|1].maxx);tree[p].hismax=max(tree[p].hismax,tree[p].maxx);
}
void add(int p,int nl,int nr,int l,int r,ll x)
{if(nl>=l && nr<=r) { tree[p].Push(x,x); return; }pushdown(p);int mid=(nl+nr)>>1;if(mid>=l) add(p<<1,nl,mid,l,r,x);if(mid<r) add(p<<1|1,mid+1,nr,l,r,x);pushup(p);
}
ll query(int p,int nl,int nr,int l,int r)
{if(nl>=l && nr<=r) return tree[p].hismax;pushdown(p);int mid=(nl+nr)>>1; ll ret=0;if(mid>=l) ret=max(ret,query(p<<1,nl,mid,l,r));if(mid<r) ret=max(ret,query(p<<1|1,mid+1,nr,l,r));pushup(p);return ret;
}
int main()
{n=rd();for(int i=1;i<=n;i++) a[i]=rd();m=rd();for(int i=1,l,r;i<=m;i++) l=rd(),r=rd(),q[r].eb(l,i);for(int r=1;r<=n;r++)// attention !! a_i\in[-100000,100000]{int Last=pre[a[r]+100000];add(1,1,n,Last+1,r,a[r]),pre[a[r]+100000]=r;for(pa v:q[r]) ans[v.se]=query(1,1,n,v.fi,r);}for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);return 0;
}