[ 可并堆 贪心 ] [ Baltic2004 ] BZOJ1367

来源:互联网 发布:python怎么创建工程 编辑:程序博客网 时间:2024/05/18 04:40

论文例题。
但论文中 zi 是单调不减的。
只要将 ti 减去 i ,这样相当于求出 zi 后再加上 i ,就是严格单调递增的了。

#include<bits/stdc++.h>using namespace std;inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());}const int N=1000010;typedef long long ll;int n,m,p,a[N];int Rt[N],ls[N],rs[N],v[N],d[N],sz[N],s[N];int top;ll Ans;int Merge(int x,int y){    if(!x||!y)return x+y;    if(v[x]<v[y])swap(x,y);    rs[x]=Merge(rs[x],y);    if(d[rs[x]]>d[ls[x]])swap(ls[x],rs[x]);    d[x]=d[rs[x]]+1;    return x;}inline void Pop(int& x){    x=Merge(ls[x],rs[x]);}inline int Abs(int x){    return x<0?-x:x;}int main(){    Read(n);    for(int i=1;i<=n;i++)Read(a[i]),a[i]-=i;    for(int i=1;i<=n;i++){        v[i]=a[i];        Rt[++top]=i;        sz[top]=s[top]=1;        while(top>1&&v[Rt[top]]<v[Rt[top-1]]){            top--;            Rt[top]=Merge(Rt[top],Rt[top+1]);            sz[top]+=sz[top+1];s[top]+=s[top+1];            while(sz[top]>(s[top]+1)>>1)Pop(Rt[top]),sz[top]--;        }    }    int j=1;    for(int i=1;i<=top;i++){        int x=v[Rt[i]];        for(int k=0;k<s[i];k++){            Ans+=Abs(x-a[j++]);        }    }    cout<<Ans<<endl;    return 0;}
原创粉丝点击