CF13C Sequence

嘟嘟嘟

 

偶然看到的这道题,觉得有点意思,就做了。

 

首先题里说修改后的数列只能出现修改前的数,那么状态之间的转移也就之可能在这些数之间。

令f[i][j]表示第 i 个数改成原序列第 j 小的数时的最小步数。容易得出:f[i][j] = min(f[i - 1][k]) + abs(a[i] - b[j]) (1 <= k <= j),其中a是原序列,b是排好序的序列。这样实现了一个O(n3)的dp。

然而n <= 5000,因此我们必须优化掉一层循环,考虑k那一层:f[i - 1][k]其实就是取前缀f[i - 1][j]中的最小值,令g[i][j]表示第 i 个数改成小于等于第 j 个数时的最小步数,那么g[i][j]可以用f[i][j]动态维护,有转移方程:

  f[i][j] = g[i - 1][j] + abs(a[i] - b[j])

  g[i][j] = f[i][j]          (j = 1)

      = min(g[i][j - 1], f[i][j])    (j > 1)

那么答案就是g[n][n]。

另外这道题限制64MB,因此空间上把第一维优化掉。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cctype>
 4 using namespace std;
 5 #define enter puts("")
 6 #define space putchar(' ')
 7 #define Mem(a, x) memset(a, x, sizeof(a))
 8 #define rg register
 9 typedef long long ll;
10 typedef double db;
11 const int INF = 0x3f3f3f3f;
12 const db eps = 1e-8;
13 const int maxn = 5e3 + 5;
14 inline ll read()
15 {
16   ll ans = 0;
17   char ch = getchar(), las = ' ';
18   while(!isdigit(ch)) las = ch, ch = getchar();
19   while(isdigit(ch)) ans = ans * 10 + ch - '0', ch = getchar();
20   if(las == '-') ans = -ans;
21   return ans;
22 }
23 inline void write(ll x)
24 {
25   if(x < 0) putchar('-'), x = -x;
26   if(x >= 10) write(x / 10);
27   putchar(x % 10 + '0');
28 }
29 
30 int a[maxn], b[maxn], n;
31 ll f[maxn], g[maxn];
32 
33 int main()
34 {
35   n = read();
36   for(int i = 1; i <= n; ++i) a[i] = b[i] = read();
37   sort(b + 1, b + n + 1);
38   for(int i = 1; i <= n; ++i)
39     for(int j = 1; j <= n; ++j)
40       {
41     f[j] = g[j] + abs(a[i] - b[j]);
42     g[j] = j == 1 ? f[j] : min(g[j - 1], f[j]);
43       }
44   write(g[n]); enter;
45   return 0;
46 }
View Code

 

转载于:https://www.cnblogs.com/mrclr/p/9755273.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值