记录编号 382632 评测结果 AAAAAAAAAA
题目名称 [HAOI 2006]数字序列 最终得分 100
用户昵称 Gravatarsxysxy 是否通过 通过
代码语言 C++ 运行时间 0.034 s
提交时间 2017-03-14 11:26:07 内存使用 1.96 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mid (l+r)/2
#define LL long long
#define inf 210000000
#define INF 2100000000000000000
const int N=36000;
int n,a[N],top=0,stack[N],f[N],tot=0,point[N],next[N],to[N];
LL g[N],sum1[N],sum2[N];
void add(int x,int y)
{
    tot+=1;
    next[tot]=point[x];
    point[x]=tot;
    to[tot]=y;
}
int abs(int x){return x<0?-x:x;}
int main()
{
  freopen("sequencec.in", "r", stdin);
  freopen("sequencec.out", "w", stdout);
    int i,j,k,l,r,now;
    scanf("%d",&n);
    for(i=1;i<=n;++i) scanf("%d",&a[i]),a[i]-=i;
    a[++n]=inf;
    stack[0]=-inf;
    for(i=1;i<=n;++i){
        if(a[i]>=stack[top]) stack[++top]=a[i],f[i]=top;
        else{
            l=1;r=top;
            while(l<=r){
                if(a[i]>=stack[mid]) l=mid+1;
                else r=mid-1;
            }
            stack[l]=a[i];
            f[i]=l;
        }
    }
    printf("%d\n",n-top);
    for(i=n;~i;--i){
        g[i]=INF;
        add(f[i],i);
    }
    a[0]=-inf;
    g[0]=0;
    for(i=1;i<=n;++i)
      for(j=point[f[i]-1];j;j=next[j]){
        now=to[j];
        if(now>i) break;
        if(a[now]>a[i]) continue;
        sum1[now-1]=sum2[now-1]=0;
        for(k=now;k<=i;++k){
            sum1[k]=sum1[k-1]+abs(a[now]-a[k]);
            sum2[k]=sum2[k-1]+abs(a[i]-a[k]);
        }
        for(k=now;k<i;++k)
          g[i]=min(g[i],g[now]+sum1[k]-sum1[now]+sum2[i]-sum2[k]);
      }
    printf("%lld\n",g[n]);
}
/*
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cstdarg>
#include <list>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
#define MAXN 360000
typedef long long LL;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fll;
int a[MAXN];
int stk[MAXN];
int f[MAXN];
LL g[MAXN], sum1[MAXN], sum2[MAXN];
vector<int> G[MAXN];
int main(){
  int n; scanf("%d", &n);
  for(int i = 1; i <= n; i++)scanf("%d", a+i);
  for(int i = 1; i <= n; i++){
    a[i] -= i;
   // f[i] = inf;
  }
  int top = 0;
  a[++n] = inf;
  stk[top] = -inf;
  for(int i = 1; i <= n; i++){
    if(a[i] >= stk[top])stk[++top] = a[i], f[i] = top;
    else{
      int l = 1, r = top;
      while(l <= r){
        int mid = (l+r)>>1;
        if(a[i] >= stk[mid])l = mid+1;
        else r = mid-1;
      }
      stk[l] = a[i];
      f[i] = l;
    }
  }
  printf("%d\n", n-top);
  for(int i = n; ~i; i--){
    g[i] = INF;
    G[f[i]].push_back(i);
  }
  a[0] = -inf;
  g[0] = 0;
  for(int i = 1; i <= n; i++){
    for(int j = 0; j < G[f[i]-1].size(); i++){
      int cur = G[f[i]-1][j];
      if(cur > i)break;
      if(a[cur] > a[i])continue;
      sum1[cur-1] = sum2[cur-1] = 0;
      for(int k = cur; k <= i; k++){
        sum1[k] = sum1[k-1]+abs(a[cur]-a[k]);
        sum2[k] = sum2[k-1]+abs(a[i]-a[k]);
      }
      for(int k = cur; k < i; k++)
        g[i] = min(g[i], g[cur]+sum1[k]-sum1[cur]+sum2[i]-sum2[k]);
    }
  }
  printf("%lld\n", g[n]);
  return 0;
}
*/