昨晚 CF C 题解
2025-12-28 13:09:47
发布于:广东
要是正开的话,结果会不一样吗?

做题顺序:C->A->C->B。
题意解析:给定一个初始长度为 的数组 。你需要对 进行 次操作。每次操作如下:
- 你可以选择 或 。
- 如果你选择 ,将得分增加 ,并删除 。
- 如果你选择 ,将得分增加 ,并删除 。
- 将剩余元素重新编号。
求最大得分。
。
思考半小时贪心无果,于是先打个 DP 再说。
注意到最终会剩一个元素,而那个元素是最终的 。
所以我们可以记 为前 操作后 是原来的 ,于是就有了很显然的 DP:
注意到这个很可以优化的样子!
首先滚动数组一下,记第 次操作前的 DP 数组为 ,操作后的 DP 数组为 ,则有如下:
显然我们需要一个方法可以快速求出 ,还要将它整体减 。
考虑一个新的 DP, 为原来的 ,这样就转化成了:
最终答案:
注意这样最开始的 应该为 而不是 。
好了,顺眼多了。那就可以用线段树维护了。
namespace cjdst{
template <typename T>
class Segtree{
std::vector <T> tr;
std::vector <int> left, right;
std::vector <T> lazytag;
void push_up(int u){
tr[u] = std::max(tr[u << 1], tr[u << 1 | 1]);
}
void push_down(int u){
tr[u << 1] += lazytag[u];
tr[u << 1 | 1] += lazytag[u];
lazytag[u << 1] += lazytag[u];
lazytag[u << 1 | 1] += lazytag[u];
lazytag[u] = 0;
}
void build(int u, int l, int r){
left[u] = l, right[u] = r;
if(l == r){
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
push_up(u);
}
void _modify(int u, int l, int r, T val){
if(left[u] >= l && right[u] <= r){
tr[u] += val;
lazytag[u] += val;
return;
}
push_down(u);
if(right[u << 1] >= l) _modify(u << 1, l, r, val);
if(left[u << 1 | 1] <= r) _modify(u << 1 | 1, l, r, val);
push_up(u);
}
T _query(int u, int l, int r){
if(left[u] >= l && right[u] <= r){
return tr[u];
}
push_down(u);
T ans = -0x3f3f3f3f3f3f3fll;
if(right[u << 1] >= l) ans = std::max(ans, _query(u << 1, l, r));
if(left[u << 1 | 1] <= r) ans = std::max(ans, _query(u << 1 | 1, l, r));
return ans;
}
public:
Segtree(){}
Segtree(int n){
tr.resize(n * 4 + 5, -0x3f3f3f3f3f3f3fll);
left.resize(n * 4 + 5);
right.resize(n * 4 + 5);
lazytag.resize(n * 4 + 5);
build(1, 1, n);
}
void modify(int l, int r, T val){
_modify(1, l, r, val);
}
T query(int l, int r){
return _query(1, l, r);
}
};
void solve(){
int n;
std::cin >> n;
std::vector <ll> a(n + 5);
for(int i = 1; i <= n; i++){
std::cin >> a[i];
}
Segtree <ll> tr(n + 5);
tr.modify(1, 1, 0x3f3f3f3f3f3f3fll + a[1]);
for(int i = 2; i <= n; i++){
tr.modify(i, i, 0x3f3f3f3f3f3f3fll + tr.query(1, i - 1) + a[i]);
tr.modify(1, i - 1, -a[i]);
}
ll ans = -0x3f3f3f3f3f3f3fll;
for(int i = 1; i <= n; i++){
ans = std::max(ans, tr.query(i, i) - a[i]);
}
std::cout << ans << '\n';
}
}
时间复杂度:。
全部评论 4
d
8小时前 来自 广东
1%%%
6小时前 来自 江西
0第一眼看成ABC了(
6小时前 来自 重庆
0%%%
6小时前 来自 重庆
0





















有帮助,赞一个