/*
if(sum[i]-sum[j]>0) f[i]=max(f[j]-j)+i;
if(sum[i]==sum[j]) f[i]=max(f[j]);
if(sum[i]-sum[j]<0) f[i]=max(f[j]+j)-i;
所以f[i] 的更新是只和f[j]有关系的
存三棵树的关系也就可以了
至于sum[i],sum[j]之间的相对关系,离散化处理一下子就可以了
然后根据s
果然,还是需要先暴力找思路,然后再对思路进行优化
屡试不爽
*/
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int M=5e5+5;
const int inf=1e17;
#define ul u<<1
#define ur u<<1|1
inline int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
struct Tree {
int l,r,v[3];
}tr[M<<2];
void pu(int u) {
for(int i=0;i<=2;i++)
tr[u].v[i]=max(tr[ul].v[i],tr[ur].v[i]);
}
void build(int u,int l,int r) {
tr[u]={l,r,{-inf,-inf,-inf}};
if(l==r)return ;
int mid=l+r>>1;
build(ul,l,mid);
build(ur,mid+1,r);
pu(u);
}
void up(int u,int x,int v0,int v1,int v2) {
if(tr[u].l==x&&tr[u].r==x) {
tr[u].v[0]=max(tr[u].v[0],v0);
tr[u].v[1]=max(tr[u].v[1],v1);
tr[u].v[2]=max(tr[u].v[2],v2);
return ;
}
if(tr[u].l>x||tr[u].r<x)return ;
up(ul,x,v0,v1,v2);
up(ur,x,v0,v1,v2);
pu(u);
}
int query(int u,int l,int r,int k) {
if(tr[u].l>=l&&tr[u].r<=r)return tr[u].v[k];
if(tr[u].l>r||tr[u].r<l)return -inf;
return max(query(ul,l,r,k),query(ur,l,r,k));
}
int a[M],b[M],sum[M];
int f[M];
signed main() {
int TT=read();
while(TT--) {
int n=read();
vector<int>v;
for(int i=1;i<=n;i++) {
a[i]=read();
f[i]=-inf;
sum[i]=sum[i-1]+a[i];
v.push_back(sum[i]);
}
build(1,1,n+1);
v.push_back(0);
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
for(int i=0;i<=n;i++)
b[i]=lower_bound(v.begin(),v.end(),sum[i])-v.begin()+1;
up(1,b[0],0,0,0);
for(int i=1;i<=n;i++) {
f[i]=max(f[i],query(1,1,b[i]-1,0)+i);
f[i]=max(f[i],query(1,b[i],b[i],1));
f[i]=max(f[i],query(1,b[i]+1,n+1,2)-i);
up(1,b[i],f[i]-i,f[i],f[i]+i);
}
cout<<f[n]<<endl;
}
return 0;
}
标签:ch,783,--,max,sum,tr,CF,int
From: https://www.cnblogs.com/basicecho/p/16991917.html