AC日记——最小正子段和 51nod 1065

Posted Only U - IU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AC日记——最小正子段和 51nod 1065相关的知识,希望对你有一定的参考价值。

最小正子段和

 

思路:

  找最小的大于0的sum[j]-sum[i](j>i);

  高级数据结构(splay)水过;

 

来,上代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 50005
#define ll long long
#define INF 0x7fffffff

struct TreeNodeType {
    ll w,key,opi,size,ch[2];
};
struct TreeNodeType tree[maxn];

ll n,tot,root,sum[maxn],ans=INF;

inline void in(ll &now)
{
    ll if_z=1;now=0;
    char Cget=getchar();
    while(Cget>9||Cget<0)
    {
        if(Cget==-) if_z=-1;
        Cget=getchar();
    }
    while(Cget>=0&&Cget<=9)
    {
        now=now*10+Cget-0;
        Cget=getchar();
    }
    now*=if_z;
}

inline ll getson(ll x)
{
    return x==tree[tree[x].opi].ch[1];
}

inline void updata(ll x)
{
    tree[x].size=tree[x].w;
    if(tree[x].ch[0]) tree[x].size+=tree[tree[x].ch[0]].size;
    if(tree[x].ch[1]) tree[x].size+=tree[tree[x].ch[1]].size;
}

void rotate(ll now)
{
    ll opi=tree[now].opi,fopi=tree[opi].opi,pos=getson(now);
    tree[opi].ch[pos]=tree[now].ch[pos^1];
    if(tree[opi].ch[pos]) tree[tree[opi].ch[pos]].opi=opi;
    tree[now].ch[pos^1]=opi,tree[now].opi=fopi;
    if(opi) tree[fopi].ch[getson(opi)]=now;
    tree[opi].opi=now,updata(opi),updata(now);
}

void splay(ll now)
{
    if(now==root) return ;
    for(ll opi;opi=tree[now].opi;rotate(now))
    {
        if(tree[opi].opi) rotate(getson(now)==getson(opi)?opi:now);
    }
    root=now;
}

void insert(ll x)
{
    if(!root)
    {
        root=++tot;
        tree[root].w=1;
        tree[root].key=x;
        tree[root].size=1;
        return ;
    }
    ll now=root,opi=0;
    while(1)
    {
        if(x==tree[now].key)
        {
            tree[now].w++,tree[now].size++;
            splay(now);
            return ;
        }
        opi=now,now=tree[now].ch[x>tree[now].key];
        if(now==0)
        {
            now=++tot;
            tree[now].w=1;
            tree[now].key=x;
            tree[now].size=1;
            tree[now].opi=opi;
            tree[opi].ch[x>tree[opi].key]=now;
            splay(now);
            return ;
        }
    }
}

ll pre()
{
    if(tree[root].w>1) return tree[root].key;
    ll now=tree[root].ch[0];if(!now) return 0;
    while(tree[now].ch[1]!=0) now=tree[now].ch[1];
    return tree[now].key;
}

int main()
{
    in(n);insert(0);
    for(ll i=1;i<=n;i++)
    {
        in(sum[i]);
        sum[i]+=sum[i-1];
        insert(sum[i]);
        ll pos=pre();
        if(sum[i]-pos>0) ans=min(ans,sum[i]-pos);
    }
    cout<<ans;
    return 0;
}

 

以上是关于AC日记——最小正子段和 51nod 1065的主要内容,如果未能解决你的问题,请参考以下文章

51 Nod 1065 最小正子段和(前缀和)

51Nod1065 最小正子段和

51nod 1065 最小正子段和

51nod-1065:最小正子段和(STL)

51nod-1065 最小正子段和 贪心 + 思维

1065 最小正子段和 二分答案 + 判定