# 【BZOJ1049】[HAOI2006]数字序列

bzoj

## 题解

### 第二问

$$g_j=min_{i=0}^{j-1}g_i+w(i,j)(dp_j=dp_i+1)$$($$w(i,j)$$表示修改区间$$[i,j]$$的贡献)

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
#define int long long
inline int gi() {
register int data = 0, w = 1;
register char ch = 0;
while (!isdigit(ch) && ch != '-') ch = getchar();
if (ch == '-') w = -1, ch = getchar();
while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar();
return w * data;
}
const int MAX_N = 35005;
const int INF = 1e13;
int N, a[MAX_N], b[MAX_N], c[MAX_N];
int f[MAX_N], g[MAX_N], s1[MAX_N], s2[MAX_N];
vector<int> vec[MAX_N];
signed main () {
N = gi(); for (int i = 1; i <= N; i++) a[i] = gi(), b[i] = a[i] - i;
fill(&f[1], &f[N + 1], INF);
for (int i = 1; i <= N; i++) c[i] = upper_bound(&f[1], &f[N + 1], b[i]) - f , f[c[i]] = b[i];
printf("%lld\n", N - (long long)(lower_bound(&f[1], &f[N + 1], INF) - f - 1));
N++; c[N] = lower_bound(&f[1], &f[N + 1], INF) - f; b[N] = INF;
fill(&g[1], &g[N + 1], INF);
b[0] = -INF;
for (int i = 0; i <= N; i++) vec[c[i]].push_back(i);
for (int i = 1; i <= N; i++) {
vector<int> :: iterator ite; int prv = c[i] - 1;
for (ite = vec[prv].begin(); ite != vec[prv].end(); ++ite) {
int k = *ite;
if (k > i) break; if (b[k] > b[i]) continue;
s1[k - 1] = s2[k - 1] = 0;
for (int j = k; j <= i; j++) s1[j] = s1[j - 1] + abs(b[k] - b[j]);
for (int j = k; j <= i; j++) s2[j] = s2[j - 1] + abs(b[i] - b[j]);
for (int j = k; j <= i; j++) g[i] = min(g[i], g[k] + s1[j] - s1[k - 1] + s2[i] - s2[j]);
}
}
printf("%lld\n", g[N]);
return 0;
}

posted @ 2018-12-26 14:37  heyujun  阅读(266)  评论(0编辑  收藏  举报