[HAOI2006]数字序列

题目描述

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

输入输出格式

输入格式:

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

输出格式:

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

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

输入输出样例

输入样例#1:
复制

4
5 2 3 5

输出样例#1: 复制

1
4

说明

【数据范围】

90%的数据n<=6000。

100%的数据n<=35000。

保证所有数列是随机的。

一份讲解的链接

先将数组每一位a[i]减i

这样单调上升就变成了不下降

在给第n+1位加一个正无穷的值(可以做所有子串的结尾,用于统计第2问的答案)

第一问:求最长不下降串长L

答案就是n-L

第二问:首先令f[i]表示1~i的最长不下降长度,g[i]为将1~i变为不下降的代价

对于一对(i,j)且f[i]=f[j]+1

设w(i,j)为将j+1~i变为单调不下降的最小代价

有一个结论:

找到一个断点k

j+1~k全部变成a[j],k+1~i全部变成a[i]

这样一定可以找到这个最小代价

证明见链接

这个复杂度很玄学,最坏O(n^3),但数据是随机的,所以远远达不到

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long lol;
 8 struct Node
 9 {
10   int next,to;
11 }edge[100001];
12 int L,n,head[40001],num,Min[40001],a[40001];
13 lol s1[40001],s2[40001],g[40001],f[40001];
14 void add(int u,int v)
15 {
16   num++;
17   edge[num].next=head[u];
18   head[u]=num;
19   edge[num].to=v;
20 }
21 int find(int x)
22 {
23   int l=0,r=L,as=0;
24   while (l<=r)
25     {
26       int mid=(l+r)/2;
27       if (Min[mid]<=x) as=mid,l=mid+1;
28       else r=mid-1;
29     }
30   return as;
31 }
32 int main()
33 {int i,j,k;
34   cin>>n;
35   for (i=1;i<=n;i++)
36     {
37       scanf("%d",&a[i]);
38       a[i]-=i;
39     }
40   ++n;
41   a[n]=(1<<30);
42   memset(Min,127,sizeof(Min));
43   Min[0]=-1<<30;L=0;
44   for (i=1;i<=n;i++)
45     {
46       int t=find(a[i]);
47       f[i]=t+1;
48       L=max(L,t+1);
49       Min[t+1]=min(Min[t+1],a[i]);
50     }
51   cout<<n-L<<endl;
52   for (i=n;i>=0;i--)
53     {
54       add(f[i],i);
55       g[i]=1ll<<60;
56     }
57   a[0]=-1<<30;g[0]=0;
58   for (i=1;i<=n;i++)
59     {
60       for (j=head[f[i]-1];j;j=edge[j].next)
61     {
62       int v=edge[j].to;
63       if (v>i) break;
64       if (a[v]>a[i]) continue;
65       for (k=v;k<=i;k++)
66         s1[k]=abs(a[k]-a[v]),s2[k]=abs(a[k]-a[i]);
67       for (k=v+1;k<=i;k++)
68         s1[k]+=s1[k-1],s2[k]+=s2[k-1];
69       for (k=v;k<i;k++)
70         g[i]=min(g[i],g[v]+s1[k]-s1[v]+s2[i]-s2[k]);
71     }
72     }
73   cout<<g[n];
74 }

原文地址:https://www.cnblogs.com/Y-E-T-I/p/8485692.html

时间: 2024-10-03 18:23:29

[HAOI2006]数字序列的相关文章

【BZOJ 1049】 [HAOI2006]数字序列

1049: [HAOI2006]数字序列 Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 979  Solved: 389 [Submit][Status] Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值. Output 第一行一个整数表示最少需要改变多少

BZOJ1049 [HAOI2006]数字序列0

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值.n<=35000

【BZOJ】1049: [HAOI2006]数字序列(lis+特殊的技巧)

http://www.lydsy.com/JudgeOnline/problem.php?id=1049 又是一题神题啊.orz 首先第一个问很容易看出 f[i]=min{f[j]+1, a[i]-a[j]>=i-j} 设b[i]=a[i]-i 得 f[i]=min{f[j]+1, b[i]>=b[j]} 然后就是lis的log算法.... 第二个问,好神!!! 首先发现,如果有b[i]>=b[j]且f[i]==f[j]+1时,区间[j, i]中的点一定都是大于b[i]或者小于b[j],

[luogu2501 HAOI2006] 数字序列 (递推LIS)

题目描述 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. 输入输出格式 输入格式: 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值. 输出格式: 第一行一个整数表示最少需要改变多少个数. 第二行一个整数,表示在改变的数最少的情况下,每个数改变的绝对值之和的最小值. 输入输出样例 输入样例#1: 4 5 2 3 5 输出样例#1: 1 4 说明 [数据范围] 90%的数据n<=6000.

[HAOI2006] 数字序列 - dp,二分

现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大.求在改变的数最少的情况下,每个数改变的绝对值之和的最小值. \(n\leq 35000\),保证数据随机 Solution 第一问很容易,只需要令 \(b_i=a_i-i\),然后跑最长不下降子序列即可 下面考虑第二问,令 \(f[i]\) 表示前 \(i\) 个数构成的数列要变成单调上升需要改动的最小幅度 若 \(a_i,a_j, i<j\) 满足

BZOJ1049: [HAOI2006]数字序列

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1049 题解: ydc的题解:http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411 第二问比较神?考场上敢去猜结论? 代码: 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring&g

p2501 [HAOI2006]数字序列

传送门 分析 https://www.luogu.org/blog/FlierKing/solution-p2501 对于第二问的感性理解就是有上下两条线,一些点在上面的线的上面或者下面的线的下面,然后看它们变成哪个线的位置更优 代码 #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<ccty

【BZOJ】【1049】【HAOI2006】数字序列

DP 第一问比较水……a[i]-=i 以后就变成最长不下降子序列问题了,第二问这个结论好神奇,考试的时候怎么破?大胆猜想,不用证明?TAT 题解:http://pan.baidu.com/share/link?uk=2651016602&shareid=1490516411 没有将a[0]置为-INF在BZOJ上WA了……so sad…… 1 /************************************************************** 2 Problem: 10

【bzoj1049】【HAOI2006】【数字序列】

1049: [HAOI2006]数字序列 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1117 Solved: 454 [Submit][Status][Discuss] Description 现在我们有一个长度为n的整数序列A.但是它太不好看了,于是我们希望把它变成一个单调严格上升的序列.但是不希望改变过多的数,也不希望改变的幅度太大. Input 第一行包含一个数n,接下来n个整数按顺序描述每一项的键值. Output 第一行一个整数表示