当前位置: 首页 > news >正文

做题记录 #2

A. ABC427G Takahashi's Expectation 2 (6.5)

非常厉害的题目。

首先肯定考虑维护一个答案函数,初始为 \(y=x\),那么每次操作相当于用一条横线砍它,上面 -b 下面 +a。

考场上想了一个正确性其实不是很显然,感觉也不一定对的东西:首先肯定时时刻刻我的斜线条数是 加入次数+1 的。因为我对断点上做一次操作,会让中间一个断点合到一起,并在两边多加一个断点。那么考虑找一下这个断点的性质,首先断点初的差分一定是 a+b,然后我认为值域有交的斜线一定定义域连续。考虑一个这样的连续段,每次切过值域重合处,会相当于把我的断点向左平移一段,然后最后加一个断点。平移量是可以简单得出的。然后维护端点位置,相当于区间减和单点插入...或许可以平衡树 /xk

正解是比较有道理的。

考虑我暴力维护这个东西。首先可以简化一下题意,默认每次一定会减掉一个 \(B\),如果我真能加就加上 \(A+B\),最后求答案的时候把答案减去 \(nB\) 即可。那么对应到它给的礼物,第 \(i\) 个礼物的价值要提高 \((i-1)B\),这样才能正确比较。这样我的过程还拥有了当前心情值不减的优美性质。不妨设 \(d=A+B\)

那么有了这个性质,我们会很想要一个递减的礼物序列。如果礼物序列递减,那么上一个礼物不能买,下一个礼物将也不能买,具有着状态单调性。这样可以二分,找到一个最后一个能买的位置,然后前面全都能买,即得出答案。但是对于相邻的两个礼物 \(x<y\) 怎么办?

讨论一下这样的对产生的贡献:一开始 \(\leq \min(x,y-d)\) 的数会被加两次 \(d\)\(\min(x,y-d)<w\leq y\) 的数会被加一次,其他的根本不加。因此这个操作 \((x,y)\) 等价于 \((\min(x,y-d),y)\)。此时的两次操作是互不干扰的!因此可以调换顺序,变为 \((y, \min(x+d,y))\)。此时右边是比左边小的,做到了改变大小关系。

那么我现在暴力去做这个操作,去维护一个递减的、与原序列等价的序列 \(c\),每次插入 \(x\) 相当于找到第一个 \(<x\)\(c_i\),将其左边插进 \(x\),再找到最后一个 \(\geq x-d\)\(c_j\),然后 Assign([i, j], x), Add([j + 1, end], a + b)。此时可以大力平衡树直接 \(mathcal{O}((n\log n)\) 爆掉,但是我不太会平衡树所以没写。如果暴力去做这个过程将会是单次操作 \(\mathcal{O}(n)\) 的。

但是这个我们其实可以做到快速合并两个有序序列!有左右相邻的两个已经变得有序的区间,可以归并地做这个操作:考虑把右侧序列一个一个插入到左侧,而且右侧序列它也是有序的,我做操作是多出来一段 \(r_i\),所以到 \(r_{i+1}\) 的时候它的 \(i\) 也不会到这个里面,所以可以双指针维护,简单合并即可。

于是可以二进制分组,查询暴力枚举块然后二分即可,查询为瓶颈,复杂度 \(\mathcal{O}(n\log^2 n)\)

Code

#pragma GCC optimize("Ofast,unroll-loops")
// STOOOOOOOOOOOOOOOOOOOOOOOOO hzt CCCCCCCCCCCCCCCCCCCCCCCORZ
#include <algorithm>
#include <cassert>
#include <iostream>
#include <numeric>
#include <vector>using namespace std;
using LL = long long;
using Block = vector<LL>;
using PII = pair<int, int>;
constexpr int kN = 2e5 + 1;int n, q;
LL A, B, d;inline void operator+=(Block &a, Block &b) {int i = 0, j = 0, cnt = 0;Block ret;for (; j < b.size(); j++) {for (; i < a.size() && a[i] + cnt * d >= b[j]; i++)ret.push_back(a[i] + cnt * d);cnt++;for (; i < a.size() && a[i] + cnt * d >= b[j]; i++)ret.push_back(b[j]);ret.push_back(b[j]);}for (; i < a.size(); ret.push_back(a[i++] + cnt * d));a.swap(ret), ret.clear();
}
vector<Block> b;
inline void Insert(LL w) {b.emplace_back(1, w);for (int sz = b.size() - 1; sz > 0 && b[sz].size() == b[sz - 1].size();) {b[sz - 1] += b[sz];b[sz].clear(), b[sz].shrink_to_fit();b.pop_back(), sz--;}
}
int main() {
#ifndef ONLINE_JUDGEfreopen("input.in", "r", stdin);freopen("output.out", "w", stdout);
#endifcin.tie(0)->sync_with_stdio(0);cin >> n >> A >> B, d = A + B;for (int i = 1, p; i <= n; i++)cin >> p, Insert(p + (i - 1) * B);cin >> q;for (LL op, x; q--;) {cin >> op >> x;if (op == 2) {for (auto &vb : b) {int l = 0, r = vb.size() - 1, ans = 0;for (int mid; l <= r;) {mid = (l + r) / 2;if (vb[mid] >= x + mid * d)l = mid + 1, ans = mid + 1;elser = mid - 1;}x += ans * d;}cout << x - 1ll * n * B << '\n';} elseInsert(x + n * B), n++;}return 0;
}
http://www.hskmm.com/?act=detail&tid=29456

相关文章:

  • 深度学习开源书籍的技术解析
  • Nginx怎么去做负载均衡?
  • 向量库面试题
  • 02 常用快捷键和指令
  • 深圳公共资源交易中心 www.szzfcg.cn
  • mysql百分数转小数点格式
  • mysql误删的performance_schema库
  • 操作系统内存管理思维导图总结
  • 15
  • 取证复刻1
  • 如何在Ubuntu中查看编辑lvgl的demo和examples?
  • 英语_翻译
  • 操作系统(Linux)文件系统思维导图总结
  • mysql不等于<>取特定值反向条件的时候字段有null值或空值读取不到数据
  • linux查看/修改各种资源限制ulimit
  • MySQL非root安装-初始化数据库时unknown variable ‘defaults-file=**/my.cnf‘
  • python中mod函数怎么用
  • Educational Codeforces Round 101 (Rated for Div. 2) 题解
  • Centos7下docker的jenkins下载并配置jdk与maven
  • The 2024 ICPC Asia Shanghai Regional Contest
  • 英语_阅读_Fireflies_待读
  • 1.基础
  • 深入解析:RoadCLIP 笔记 针对自动驾驶优化的 CLIP 变体 vlm
  • ASP.NET Razor VB 变量 - 实践
  • dos命令和命令提示符
  • 20232401 2025-2026-1 《网络与系统攻防技术》实验一实验报告
  • for 循环 range
  • 在AI技术唾手可得的时代,挖掘新需求成为核心竞争力——某知名离线转录工具需求洞察
  • JavaScript async/await 基础使用
  • 27. 移除元素 暴力+快慢指针+相向双指针