P8476 「GLR-R3」惊蛰 题解
笔记列表
天依题
\天依/\天依/\天依/
笔记列表
首先可以想到一个朴素 \(dp\),设 \(g_{i,j}\) 表示第 \(i\) 位 \(b_i=j\) 时的最小代价
转移 \(g_{i,j}=min_{k\ge j}^{} g_{i-1,k} + f(j,a_i)\)
优化它,先给 \(g\) 上一个后缀取最小值,即 \(h_{i,j}=min(g_{i,j},h_{i,j+1})\)
转移变成了 \(g_{i,j} = h_{i-1,j} + f(j,a_i)\)
然后发现 \(g\) 是分段单调不降的
因为首先后缀最小值是单调不降的 \(h_{i,j}\leq h_{i,j+1} \leq h_{i,j+2} \leq ...\)
然后在这个单调不降的东西的基础上加了一个 \(f(j,a_i)\)
-
当 \(j<a_i\) 时,加的是一个常数, 所以 \([1,a_i]\) 是单调不降的
-
当 \(j \ge a_i\) 时, \(j\) 越大加的越多,然后两个单调不降和起来还是单调不降,所与 \([a_i+1,len]\) 还是单调不降的
重要结论:每一个 \(g_i\) 在进行求后缀最小值这一步之前是分段单调不降的
然后这个时候我们就线段数实现以下两个功能
- 每一轮快速的算出所有 \(g_{i,j}\)
- 每一轮快速的对 \(g\) 做后缀取最小值运算 \(g_{i,j}=min(g_{i,j},g_{i,j+1})\)
第一个功能
- 首先需要对 \(a_i\) 离散化, 因为你的 \(b_i\) 如果填写的如果时没有出现过的 \(a\) 值肯定没有必要
- 枚举当前的 \(i\)
- 让线段数的每一个位置的值表示 \(g_{i,j}\)
- 现在线段数上是上一轮求的 \(g_{i-1,j}\)
- 这里上一轮已经对 \(g_{i-1}\)做完了求后缀最小值的操作,所以 \(g_{i-1}\) 整体是单调不降的
- 要求出 \(g_{i,j}\)
- 根据转移公式给 \([1,a_i-1]\) 区间加 \(C\);
- 给\([a_i+1,len] 加上 b_i-i\)
- 这里 \(b_i\) 表示离散化之前的原值
- 第一个只需要支持区间加法就可以满足
- 第二个可以让线段数记录一个懒标记,表示区间内每一个位置加了多少个 \(b_i\)
第二个功能
- 现在的 \(g\) 做完了转移,我们要对他求后缀最小值
- 根据结论现在的 \(g\) 应该是分段单调不降的
- 所以会在求后缀最小值更新的情况一定是后半段\([a_i+1, len]\)的最小值 \(g_{i,a_i}\) 更新了 前半段 \([1,a_i]\) 的一个后缀
- 那么我们找到 \([1,len]\) 中 从左到右 第一个大于等于 \(g_{i,a_i}\) 的位置\(pos\),然后区间修改\([pos+1,i-1]\) 赋值成 \(g_{i,a_i}\)
- 这样就实现了后缀最小值更新的功能
最后一个位置填什么都可以,取最小值所以答案就是
\[min_j^{}\;g_{n,j}
\]
点击查看代码
#include<bits/stdc++.h>
#define int long long
#define fore(i,a,b) for( int i=(a); i<=(b); ++i)
#define repe(i,a,b) for( int i=(a); i>=(b); --i)
using namespace std;
const int N = 1e6 + 10;
int n, C;
int a[N];
int b[N];
int lsh[N], len;
inline int ls(int p) {
return (p << 1);
}
inline int rs(int p) {
return ((p << 1) | 1);
}
struct Segtr {
int t[N << 2];
int add[N << 2], mul[N << 2], tag[N << 2];
inline void pushup(int p) {
t[p] = max(t[ls(p)], t[rs(p)]);
}
void build(int p,int l,int r) {
add[p] = 0; mul[p] = 0;
tag[p] = -1;
if(l == r) {
return;
}
int mid = (l + r) >> 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
pushup(p);
}
void updateson(int p,int r,int Add,int Mul,int Tag) {
if(Tag != -1) {
t[p] = Tag;
tag[p] = Tag;
add[p] = 0;
mul[p] = 0;
// return;
}
mul[p] += Mul;
add[p] += Add;
t[p] = t[p] + Add + Mul * b[r];
}
void pushdown(int p,int l,int r) {
if(add[p] == 0 && mul[p] == 0 && tag[p] == -1) return;
int mid = (l + r) >> 1;
updateson(ls(p), mid, add[p], mul[p], tag[p]);
updateson(rs(p), r, add[p], mul[p], tag[p]);
add[p] = mul[p] = 0;
tag[p] = -1;
}
void update(int p,int l,int r,int L,int R,int Add,int Mul,int Tag) {
if(L > R) return;
if(L <= l && r <= R) {
updateson(p, r, Add, Mul, Tag);
return;
}
pushdown(p, l, r);
int mid = (l + r) >> 1;
if(L <= mid) update(ls(p), l, mid, L, R, Add, Mul, Tag);
if(R >= mid + 1) update(rs(p), mid + 1, r, L, R, Add, Mul, Tag);
pushup(p);
}
int querypos(int p,int l,int r,int pos) {
if(l == r) {
return t[p];
}
pushdown(p, l, r);
int mid = (l + r) >> 1;
if(pos <= mid) return querypos(ls(p), l, mid, pos);
return querypos(rs(p), mid + 1, r, pos);
}
int find(int p, int l, int r, int pos, int val) {
if (r <= pos && t[p] < val) return -1;
if (l == r) return l;
int mid = (l + r) >> 1;
pushdown(p, l, r);
int res = find(ls(p), l, mid, pos, val);
if (res != -1) return res;
if (mid < pos) return find(rs(p), mid + 1, r, pos, val);
return -1;
}
} T;
signed main(){
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin >> n >> C;
fore(i, 1, n) {
cin >> a[i];
lsh[++ len] = a[i];
}
sort(lsh + 1, lsh + len + 1);
len = unique(lsh + 1, lsh + len + 1) - lsh - 1;
fore(i, 1, n) {
int x = lower_bound(lsh + 1, lsh + len + 1, a[i]) - lsh;
b[x] = a[i];
a[i] = x;
}
T.build(1, 1, len);
fore(i, 1, n) {
T.update(1, 1, len, 1, a[i] - 1, C, 0, -1);
T.update(1, 1, len, a[i] + 1, len, -b[a[i]], 1, -1);
int val = T.querypos(1, 1, len, a[i]);
int pos = T.find(1, 1, len, a[i] - 1, val);
if(pos == -1) continue;
T.update(1, 1, len, pos, a[i] - 1, 0, 0, val);
}
int ans = 1e18;
fore(i, 1, len) ans = min(ans, T.querypos(1, 1, len, i));
cout << ans << '\n';
return 0;
}
本文来自博客园,作者:wmq2012,转载请注明原文链接:https://www.cnblogs.com/wmq2012/p/23074372

浙公网安备 33010602011771号