【BZOJ2482】【SPOJ1557】GSS2
离线处理+线段树即可。
离线,将所有询问按右端点从小到大排序,从小到大枚举答案区间的右端点,维护表示中不同值的和,每次把加上,不难发现询问的答案是中所有元素的历史最大值的最大值。
于是问题就变成了:维护一个数据结构,支持区间加一个数,询问区间历史最大值的最大值。
线段树维护当前最大值,历史最大值。标记当前需要加上的,历史最大的。注意标记有时间顺序,所以需要pushdown
。
#include <bits/stdc++.h>
using namespace std;
const int MAXSIZE=30000020;
int bufpos;
char buf[MAXSIZE];
void init(){
buf[fread(buf,1,MAXSIZE,stdin)]='\0';
bufpos=0;
}
int readint(){
bool isneg;
int val=0;
for(;!isdigit(buf[bufpos]) && buf[bufpos]!='-';bufpos++);
bufpos+=(isneg=(buf[bufpos]=='-'))?1:0;
for(;isdigit(buf[bufpos]);bufpos++)
val=val*10+buf[bufpos]-'0';
return isneg?-val:val;
}
char readchar(){
for(;isspace(buf[bufpos]);bufpos++);
return buf[bufpos++];
}
int readstr(char* s){
int cur=0;
for(;isspace(buf[bufpos]);bufpos++);
for(;!isspace(buf[bufpos]);bufpos++)
s[cur++]=buf[bufpos];
s[cur]='\0';
return cur;
}
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3fLL;
struct tag{
ll add,curadd;
tag(ll x=0){
add=x;
curadd=max(x,0LL);
}
tag& operator +=(const tag& rhs){
curadd=max(curadd,add+rhs.curadd);
add+=rhs.add;
return *this;
}
};
struct atom{
ll mmax,curmax;
atom(){
mmax=curmax=0;
}
atom(ll mmax,ll curmax){
this->mmax=mmax,this->curmax=curmax;
}
atom operator +(const atom& rhs)const{
return atom(max(mmax,rhs.mmax),max(curmax,rhs.curmax));
}
atom& operator +=(const atom& rhs){
return *this=*this+rhs;
}
atom operator +(const tag& x)const{
return atom(mmax+x.add,max(curmax,mmax+x.curadd));
}
atom& operator +=(const tag& x){
return *this=*this+x;
}
};
const int maxn=100001;
struct segtree{
static const int maxt=maxn*4;
atom t[maxt];
tag v[maxt];
int n;
void init(int n){
this->n=n;
}
void pushdown(int o){
v[o*2]+=v[o];
t[o*2]+=v[o];
v[o*2+1]+=v[o];
t[o*2+1]+=v[o];
v[o]=tag();
}
int ul,ur,uv;
void update(int o,int l,int r){
if (ul<=l && ur>=r){
t[o]+=uv;
v[o]+=uv;
return;
}
pushdown(o);
int mid=(l+r)/2;
if (ul<=mid)
update(o*2,l,mid);
if (ur>mid)
update(o*2+1,mid+1,r);
t[o]=t[o*2]+t[o*2+1];
}
int ql,qr;
atom query(int o,int l,int r){
if (ql<=l && qr>=r)
return t[o];
int mid=(l+r)/2;
atom res;
res.mmax=-INF;
if (ql<=mid)
res+=query(o*2,l,mid);
if (qr>mid)
res+=query(o*2+1,mid+1,r);
return res+v[o];
}
}t;
struct query{
int p,l,r;
bool operator <(const query& rhs)const{
return r<rhs.r;
}
}q[maxn];
const int delta=100000;
int now[200003];
int a[maxn];
bool vis[200003];
int lst[maxn];
ll ans[maxn];
int main(){
init();
int n=readint();
t.init(n);
for(int i=1;i<=n;i++){
a[i]=readint();
lst[i]=now[a[i]+delta];
now[a[i]+delta]=i;
}
int m=readint();
for(int i=1;i<=m;i++)
q[i].p=i,q[i].l=readint(),q[i].r=readint();
sort(q+1,q+m+1);
int now=1;
for(int i=1;i<=m;i++){
while(now<=q[i].r){
t.ul=lst[now]+1;
t.ur=now;
t.uv=a[now];
t.update(1,1,n);
now++;
}
t.ql=q[i].l,t.qr=q[i].r;
ans[q[i].p]=t.query(1,1,n).curmax;
}
for(int i=1;i<=m;i++)
printf("%lld\n",ans[i]);
}
本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
本文链接:https://www.q234rty.top/2017/04/29/bzoj2482/