[dp][瞎搞] 洛谷 P2501 数字序列

题目描述

现在我们有一个长度为n的整数序列A。但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列。但是不希望改变过多的数,也不希望改变的幅度太大。

输入输出格式

输入格式:

 

第一行包含一个数n,接下来n个整数按顺序描述每一项的键值。

 

输出格式:

 

第一行一个整数表示最少需要改变多少个数。

第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值。

 

输入输出样例

输入样例#1:
4
5 2 3 5
输出样例#1:
1
4

说明

【数据范围】

90%的数据n<=6000。

100%的数据n<=35000。

保证所有数列是随机的。

 

题解

  • 我们可以把序列中的每个数减去他们的位置构成一个新的序列,a[i]-=i
  • 对于第一问,我们可以求最多有多少个点不用修改,就是最长不下降子序列,答案就是n-最长不下降子序列的长度
  • 对于第二问,就是求把这个序列转换成最长不下降子序列的最小代价
  • 证明对于[i,j]的一段区间并且满足f[i]+1=f[j]和a[i]<=a[j]
  • 我们把它变成不下降的最小代价一定是从中间取一个点t,我们把[i+1,t]全都变成a[i],[t+1,j-1]全都变成a[j]
  • 大爷的证明如下:
  • 这样我们枚举t就好了,因为随机数据嘛,应该可以过的

代码

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <iostream>
 4 using namespace std;
 5 #define inf 210000000
 6 const int N=35010;
 7 int n,cnt,top,a[N],Q[N],f[N],head[N];
 8 long long g[N],x[N],y[N];
 9 struct edge {int to,from;}e[N];
10 void insert(int x,int y) { e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt; }
11 int main()
12 {
13     scanf("%d",&n);
14     for (int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]-=i;
15     a[++n]=inf,Q[0]=-inf;
16     for (int i=1;i<=n;i++)
17         if (a[i]>=Q[top]) Q[++top]=a[i],f[i]=top;
18         else 
19         {
20             int l=1,r=top;
21             while (l<=r)
22             {
23                 int mid=l+r>>1;
24                 if (a[i]>=Q[mid]) l=mid+1; else r=mid-1;
25             }
26             Q[l]=a[i],f[i]=l;
27         }
28     printf("%d\n",n-top);
29     for (int i=n;~i;i--) g[i]=inf*1e5,insert(f[i],i);
30     a[0]=-inf,g[0]=0;
31     for (int i=1;i<=n;i++)
32         for (int j=head[f[i]-1];j;j=e[j].from)
33         {
34             if (e[j].to>i) break;
35             if (a[e[j].to]>a[i]) continue;
36             x[e[j].to-1]=y[e[j].to-1]=0;
37             for (int k=e[j].to;k<=i;k++) x[k]=x[k-1]+abs(a[e[j].to]-a[k]),y[k]=y[k-1]+abs(a[i]-a[k]);
38             for (int k=e[j].to;k<i;k++) g[i]=min(g[i],g[e[j].to]+x[k]-x[e[j].to]+y[i]-y[k]);
39         }
40     printf("%lld",g[n]);
41 }

 

posted @ 2019-02-21 16:39  BEYang_Z  阅读(520)  评论(0编辑  收藏  举报