bzoj1049: [HAOI2006]數字序列

我也貼一個233

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int read()
{
    char ch=getchar();int f=0,x=1;
    while(ch<'0'||ch>'9'){if(ch=='-') x=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){f=(f<<1)+(f<<3)+ch-'0';ch=getchar();}
    return f*x;
}
int n;
struct node
{
    int from;
    int to;
    int next;
}edge[50005];
int head[50005],a[50005],aa[50005];
int f[50005],mn[50005],tot,L;
long long g[50005],s1[50005],s2[50005];
void add(int u,int v)
{
    edge[tot].from=u;
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void solve()
{
    for(int i=n;i>=0;i--)
    {
        add(f[i],i);
        g[i]=1LL<<60;
    }
    g[0]=0;a[0]=-(1<<30);
    for(int x=1;x<=n;x++)
    {
        for(int i=head[f[x]-1];i!=-1;i=edge[i].next)
        {
            if(edge[i].to>x) break;
            if(a[edge[i].to]>a[x]) continue;
            for(int j=edge[i].to;j<=x;j++)
            s1[j]=abs(a[edge[i].to]-a[j]),s2[j]=abs(a[x]-a[j]);
            for(int j=edge[i].to+1;j<=x;j++)
            s1[j]+=s1[j-1],s2[j]+=s2[j-1];
            for(int j=edge[i].to;j<x;j++)
            {
                g[x]=min(g[x],g[edge[i].to]+s1[j]-s1[edge[i].to]+s2[x]-s2[j]);
            }
        }
    }
}
int find(int x)
{
    int l=1,r=L,t=0;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(mn[mid]<=x)t=mid,l=mid+1;
        else r=mid-1;
    }
    return t;
}
int main()
{
    memset(head,-1,sizeof(head));
    n=read();
    for(int i=1;i<=n;i++)
    {
        aa[i]=read();
        a[i]=aa[i]-i;
    }
    a[++n] =(1<<30);
    memset(mn,127,sizeof(mn));
    mn[0]=-(1<<30);
    for(int i=1;i<=n;i++)
    {
        int t=find(a[i]);
        f[i]=t+1;
        L=max(L,t+1);
        mn[t+1]=min(mn[t+1],a[i]);
    }
    printf("%d\n",n-f[n]);
    solve();
    printf("%lld",g[n]);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章