传送门:https://codeforces.com/contest/1668/problem/D
思路:dp+树状数组, 参考博客https://www.cnblogs.com/Prgl/p/16169339.html
需要注意dp初始化时需要把0先算上去,即假设数列的左边隐含着一个为0的元素做分割线
Code:
#include<iostream>
#include<algorithm>
#include<set>
#include<unordered_map>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pr;
const int MAX_N=5e5+5;
int n,m,T;
LL a[MAX_N];
int mx[MAX_N];
int C1[MAX_N],C2[MAX_N];
set<LL> st;
unordered_map<LL,int> id;
int Lowbit(int x);
void Update(int C[],int id,int x);
int Query(int C[],int id);
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin>>T;
int res;
LL x;
while(T--){
st.clear();
st.insert(0);
cin>>n;
for(int i=1;i<=n;++i)
{
cin>>x;
a[i]=a[i-1]+x;
st.insert(a[i]);
C1[i]=C2[i]=mx[i]=-1e9;
}
C1[n+1]=C2[n+1]=mx[n+1]=-1e9;
m=0;
for(auto val:st)
{
id[val]=++m;
}
swap(n,m);
for(int i=0;i<=m;++i)
{
x=a[i];
if(i==0){
res=0;
}else{
res=max(mx[id[x]],max(Query(C1,id[x]-1)+i,Query(C2,n-id[x])-i));
}
Update(C1,id[x],res-i);
Update(C2,n-id[x]+1,res+i);
mx[id[x]]=max(mx[id[x]],res);
}
cout<<res<<endl;
}
}
int Lowbit(int x)
{
return x&(-x);
}
void Update(int C[],int id,int x)
{
while(id<=n){
C[id]=max(C[id],x);
id+=Lowbit(id);
}
}
int Query(int C[],int id)
{
int ans=-1e9;
while(id>0){
ans=max(ans,C[id]);
id-=Lowbit(id);
}
return ans;
}