https://codeforces.com/problemset/problem/1359/D
这题一看发现是枚举最大值,维护所有存在的区间,并用线段树维护区间最大子段和。。。然后发现E只比这题少过一点人,就果断先开的E,以为这道题真的这么难。
写完了以后150行,还拿样例逐步调试看哪里有问题没有最后才敢交,结果最后学弟说20行,只要枚举最大值,然后从前往后扫得到最大值就行了。。。日
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
int n,m,ans,cas,k;
int a[maxl];
vector<int> b[31];
bool in[maxl];
struct node
{
int l,r,sum,lrmx;
int rmx,lmx;
}tree[maxl*4];
struct lne
{
int l,r;
bool operator <(const lne &b)const
{
if(l==b.l)
return r<b.r;
return l<b.l;
}
bool operator ==(const lne &b)const
{
return l==b.l && r==b.r;
}
};
set <lne> s;
inline void pushup(int k)
{
int ls=k<<1,rs=k<<1|1;
tree[k].sum=tree[ls].sum+tree[rs].sum;
tree[k].lrmx=max(tree[ls].lrmx,tree[rs].lrmx);
tree[k].lrmx=max(tree[k].lrmx,tree[ls].rmx+tree[rs].lmx);
tree[k].lmx=max(tree[ls].lmx,tree[rs].lmx+tree[ls].sum);
tree[k].rmx=max(tree[rs].rmx,tree[ls].rmx+tree[rs].sum);
}
inline void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;
if(l==r)
{
tree[k].sum=a[l];
tree[k].lrmx=tree[k].lmx=tree[k].rmx=max(0,a[l]);
return;
}
int mid=(l+r)>>1,ls=k<<1,rs=k<<1|1;
build(ls,l,mid);
build(rs,mid+1,r);
pushup(k);
}
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]>0)
b[a[i]].push_back(i);
}
build(1,1,n);
lne d;
for(int i=1;i<=n;i++)
if(a[i]<=0)
{
d.l=i;d.r=i;
while(d.r+1<=n && a[d.r+1]<=0)
d.r++;
s.insert(d);i=d.r;
}
}
inline node qry(int k,int l,int r)
{
node ret,y,z;
if(tree[k].l==l && tree[k].r==r)
return tree[k];
int mid=(tree[k].l+tree[k].r)>>1;
if(r<=mid)
return qry(k<<1,l,r);
else if(l>mid)
return qry(k<<1|1,l,r);
else
{
z=qry(k<<1,l,mid);
y=qry(k<<1|1,mid+1,r);
ret.l=z.l;ret.r=y.r;
ret.sum=z.sum+y.sum;
ret.lrmx=max(z.lrmx,y.lrmx);
ret.lrmx=max(ret.lrmx,z.rmx+y.lmx);
ret.lmx=max(z.lmx,y.lmx+z.sum);
ret.rmx=max(y.rmx,z.rmx+y.sum);
}
return ret;
}
inline void mainwork()
{
lne tmp,nlne;set <lne>::iterator z,y;
node ret;ans=0;
for(int num=1;num<=30;num++)
for(int id:b[num])
{
tmp.l=tmp.r=id;
z=s.lower_bound(tmp);
if(z!=s.begin())
{
--z;
if(tmp.l==(*z).r+1)
{
nlne.l=(*z).l;nlne.r=tmp.r;
ret=qry(1,nlne.l,nlne.r);
s.erase(z);
ans=max(ans,ret.lrmx-num);
tmp=nlne;
}
}
y=s.lower_bound(tmp);
if(tmp.r==(*y).l-1)
{
nlne.l=tmp.l;nlne.r=(*y).r;
ret=qry(1,nlne.l,nlne.r);
s.erase(s.lower_bound(tmp));
ans=max(ans,ret.lrmx-num);
tmp=nlne;
}
s.insert(tmp);
}
}
inline void print()
{
printf("%d",ans);
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}