CF--783--D

D. Optimal Partition

/*
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;
}
posted @ 2022-12-19 13:14  basicecho  阅读(47)  评论(0)    收藏  举报