P2501 [HAOI2006] 数字序列
[题目链接]([P2501 HAOI2006] 数字序列 - 洛谷 | 计算机科学教育新生态)
首先是第一问,直接求不好求,我们们考虑求不用更改的数量,发现有这个性质,如果,a[i] - a[j] < abs(j - i)两个数的差值能满足他们之间有足够多数的情况,例如1 4 5 3,取1 和 3,那么就有2 < 3, 中间的4 和 5 怎么改也不会单调上升
所以, 经过移项得a[i] - i < a[j] - j 即可,这就具有了,求最长的上升a[i] - i 即可,用b数组存下来是求最大上身子序列
这是第一问
第二问我们假如以i为最后一位的子序列的前一个状态时pre[i] 我们要把之间的数全都修改一遍,那就得让左边某一部分等于b[from],另一部分等于b[i],枚举这个分区即可求得从from到i这区间变为单调递增的最小花费,总花费加上from之前的就行
// Problem: P2501 [HAOI2006] 数字序列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2501
// Memory Limit: 125 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//by codeforcer ——
// ____ _ _ _ _ _ _ ____ _
// / ___|| | | || | | || | | | |___ \ | |
//| | | |_| || |_| || |_| | __) | | |
//| | | _ || _ || _ | |__ < | |
//| |___ | | | || | | || | | | ___) | | |
// \____||_| |_||_| |_||_| |_| |____ / |_|
#include<bits/stdc++.h>
using namespace std;
typedef int E;
typedef long long LL;
typedef pair<int, int> PII;
typedef tuple<int, int, int> PIII;
typedef tuple<LL, LL, LL> PLLL;
typedef pair<long long, long long> PLL;
typedef unsigned long long ULL;
#define endl '\n'
#define vec vector
#define pb push_back
#define pob pop_back
#define fir first
#define sec second
#define maxINT 0x3f3f3f3f
#define maxLL 0x3f3f3f3f3f3f3f3fLL
#define umap unordered_map
#define uset unordered_set
#define maxheap priority_queue<E, vector<E>, less<E>>
#define minheap priority_queue<E, vector<E>, greater<E>>
#define prvec(a) \
for (int i = 0; i < (a).size(); i++) { \
cout << (a)[i] << " "; \
} \
cout << endl;
#define debugvec(a, i, n) \
cout << #a << ": "; \
for (int k = (i); k <= (n); k++) { \
cout << (a)[k] << " "; \
} \
cout << endl;
LL gcd(LL a, LL b) { return (b) ? gcd(b, a % b) : a; }
LL exgcd(LL a, LL b, LL &x, LL &y) {if (b == 0) { x = 1, y = 0; return a; }LL gcd = exgcd(b, a % b, y, x);y -= a / b * x;return gcd;}
LL qmi(LL a, LL b, LL mod) {LL res = 1;while (b) {if (b & 1) res = res * a % mod;a = a * a % mod;b >>= 1;}return res;}
const int N = 3e4 + 5e3;
long long top[N],f[N],g[N];
long long pre[N],sub[N],b[N];
vector<int> ed[N];
void solve() {
int n;
cin>>n;
vec<long long> a(n + 3);
for(int i = 1;i <= n;i ++)
{
cin>>a[i];
b[i] = a[i] - i;
}
b[0] = -(1e9+2093),b[n + 1] = 1e9 + 2330;
int cnt = 0;
for(int i = 1;i <= n+1;i ++)
{
int l = 0,r = cnt;
while(l < r)
{
int mid = (l + r + 1)>>1;
if(top[mid] <= b[i])
{
l = mid;
}else r = mid - 1;
}
if(l == cnt) cnt ++;
f[i] = l + 1;
top[l + 1] = b[i];
ed[f[i]].pb(i);
}
ed[0].pb(0);
memset(g,20,sizeof g);
g[0] = 0;
for(int i = 1;i <= n+1;i ++)
{
for(int j = 0;j < ed[f[i] - 1].size();j ++)
{
int from = ed[f[i] - 1][j];
if(from > i || b[from] > b[i]) continue;
pre[from] = sub[i - 1] = 0;
for(int k = from + 1;k <= i - 1;k ++)
{
pre[k] = pre[k - 1] + abs(b[k] - b[from]);
}
for(int k = i - 2;k >= from;k --)
{
sub[k] = sub[k + 1] + abs(b[k + 1] - b[i]);
}
for(int k = from;k <= i - 1;k ++)
{
g[i] = min(g[i],g[from] + pre[k] + sub[k]);
}
}
}
cout<<n - cnt+1<<endl<<g[n + 1]<<endl;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
solve();
return 0;
}