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

LG P2617 Dynamic Rankings Solution

Preface

刚才在另一篇题解里提到了这个题,来补一下.

Description

给定序列 a=(a1,a2,⋯ ,an)a=(a_1,a_2,\cdots,a_n)a=(a1,a2,,an),有 qqq 次操作分两种:

  • Q l r k:求 al∼ara_l\sim a_ralar 中第 kkk 小的数.
  • C x y:令 ax←ya_x\gets yaxy.

Limitations

1≤n,q≤1051\le n,q\le 10^51n,q105
1≤l≤r≤n,1≤k≤r−l+11\le l\le r\le n,1\le k\le r-l+11lrn,1krl+1
1≤x≤n,1≤ai,y≤1091\le x\le n,1\le a_i,y\le 10^91xn,1ai,y109
3s,512MB3\text{s},512\text{MB}3s,512MB

Solution

题目没有强制在线,可以全部离线下来.
由于要求第 kkk 小,自然想到整体二分.
首先对所有 ai,ya_i,yai,y 离散化,并把 C 操作拆成一次删除 aia_iai 和一次插入 yyy.
设当前处理到值域区间(离散化后)为 [s,t][s,t][s,t]mmm 为当前的中点,QQQ 为当前的操作列表.
s=ts=ts=t 则每个查询的答案都为 sss.
否则,我们用一个 BIT 来维护当前 aaa≤m\le mm 的数个数,考虑 QQQ 中的每个操作:

  • 若为查询操作,我们在 BIT 上查 al∼ara_l\sim a_ralar≤m\le mm 的数个数(设为 ppp),如果 p≥kp\ge kpk,就把 TTT 放到 QLQ_LQL 中,否则令 k←k−pk\gets k-pkkp 后放到 QRQ_RQR 中.

  • 若为插入或删除操作,如果 y≤my\le mym,那么就在 BIT 上修改,并放入 QLQ_LQL,否则直接放入 QRQ_RQR.

处理全部操作后,递归 ([s,m],QL)([s,m],Q_L)([s,m],QL)([m+1,t],QR)([m+1,t],Q_R)([m+1,t],QR) 继续处理,不过在这之前需要撤掉 BIT 上的所有修改.

至于理解,可以想一下 qqq 次二分同步进行.
由于要分治 O(log⁡n)O(\log n)O(logn) 层,BIT 单次修改 O(log⁡n)O(\log n)O(logn),故时间复杂度为 O(nlog⁡2n)O(n\log^2 n)O(nlog2n),空间复杂度 O(n)O(n)O(n),但比树套树常数小得多.

Code

3.95KB,2.86s,17.44MB  (c++20 with o2)3.95\text{KB},2.86\text{s},17.44\text{MB}\;\texttt{(c++20 with o2)}3.95KB,2.86s,17.44MB(c++20 with o2)

// Problem: P2617 Dynamic Rankings
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2617
// Memory Limit: 512 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;template<class T>
bool chmax(T &a, const T &b){if(a < b){ a = b; return true; }return false;
}template<class T>
bool chmin(T &a, const T &b){if(a > b){ a = b; return true; }return false;
}struct Node {int tp, val;int le, ri;int pos;Node(int _tp = 0, int _val = 0, int _le = 0, int _ri = 0, int _pos = 0):tp(_tp), val(_val), le(_le), ri(_ri), pos(_pos) {}
};int lowbit(int x){return x & -x;
}template<class T>
struct fenwick{int n;vector<T> c;fenwick() {}fenwick(int _n): n(_n){c.resize(n + 1);}fenwick(const vector<T> &a): n(a.size()){c.resize(n + 1);for(int i = 1; i <= n; i++){c[i] = c[i] + a[i - 1];int j = i + lowbit(i);if(j <= n) c[j] = c[j] + c[i];}}void add(int x, const T& v){for(int i = x + 1; i <= n; i += lowbit(i)) c[i] = c[i] + v;}T ask(int x){T ans{};for(int i = x + 1; i; i -= lowbit(i)) ans = ans + c[i];return ans;}T ask(int l, int r){return ask(r) - ask(l - 1);}
};signed main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n, m;cin >> n >> m;vector<int> a(n), nums;vector<Node> tasks, tmp;for (int i = 0; i < n; i++) {cin >> a[i];nums.push_back(a[i]);tasks.emplace_back(1, a[i], -1, -1, i);}for (int i = 0; i < m; i++) {char op;cin >> op;if (op == 'Q') {int l, r, k;cin >> l >> r >> k;l--, r--;tasks.emplace_back(0, k, l, r, i);}else {int p, v;cin >> p >> v;p--;tasks.emplace_back(-1, a[p], -1, -1, p);tasks.emplace_back(1, v, -1, -1, p);nums.push_back(v);a[p] = v;}}sort(nums.begin(), nums.end());nums.erase(unique(nums.begin(), nums.end()), nums.end());for (auto &task : tasks) {if (task.tp == 0) {continue;}int p = lower_bound(nums.begin(), nums.end(), task.val) - nums.begin();task.val = p;}vector<int> ans(m, -1);fenwick<int> f(n);auto solve = [&](auto &&self, int l, int r, int lo, int hi) -> void {if (l >= r) {return;}if (lo == hi) {for (int i = l; i <= r; i++) {if (tasks[i].tp == 0) {ans[tasks[i].pos] = lo;}}return;}int mid = (lo + hi) / 2;vector<Node> tl, tr;for (int i = l; i <= r; i++) {if (tasks[i].tp) {if (tasks[i].val <= mid) {f.add(tasks[i].pos, tasks[i].tp);tl.push_back(tasks[i]);}else {tr.push_back(tasks[i]);}}else {int cnt = f.ask(tasks[i].le, tasks[i].ri);if (cnt >= tasks[i].val) {tl.push_back(tasks[i]);}else {tasks[i].val -= cnt;tr.push_back(tasks[i]);}}}for (int i = l; i <= r; i++) {if (tasks[i].tp && tasks[i].val <= mid) {f.add(tasks[i].pos, -tasks[i].tp);}}copy(tl.begin(), tl.end(), tasks.begin() + l);copy(tr.begin(), tr.end(), tasks.begin() + l + tl.size());self(self, l, l + tl.size() - 1, lo, mid);self(self, l + tl.size(), r, mid + 1, hi);};solve(solve, 0, tasks.size() - 1, 0, nums.size() - 1);for (int i = 0; i < m; i++) {if (ans[i] != -1) {cout << nums[ans[i]] << endl;}}return 0;
}
http://www.dtcms.com/a/343473.html

相关文章:

  • 1688 商品详情接口数据全解析(1688.item_get)
  • 关于从零开始写一个TEE OS
  • 如何安装 VMware Workstation 17.5.1?超简单步骤(附安装包下载)
  • Building Systems with the ChatGPT API 使用 ChatGPT API 搭建系统(第四章学习笔记及总结)
  • 一文讲清楚:场景、痛点、需求
  • mainMem.useNamedFile = “FALSE“ 的效果
  • UE5多人MOBA+GAS 52、下载源码构建引擎
  • 如何处理项目中棘手的依赖版本冲突问题
  • 软考中级【网络工程师】第6版教材 第3章 局域网 (下)
  • 构造参数注入解决循环依赖问题
  • 射频电路的完整性简略
  • rt-thread使用sfud挂载qspi flash的trace分析
  • Linux ELF二进制文件数字签名工具:原理与设计思路(C/C++代码实现)
  • SQL聚合情景解读
  • 【笔记】Facefusion3.3.2 之 NSFW 检测屏蔽测试
  • 代码随想录算法训练营27天 | ​​56. 合并区间、738.单调递增的数字、968.监控二叉树(提高)
  • 机器学习6
  • 机器学习-聚类算法
  • 告别研发乱局,决胜项目先机——全星APQP系统,为汽车部件制造商量身打造的数字化研发管理引擎
  • GPT5 / 深度研究功能 无法触发
  • 4.Shell脚本修炼手册---变量进阶知识
  • 加速你的故障排查:使用 Elasticsearch 构建家电手册的 RAG 应用
  • 如何实现文档处理全流程自动化?
  • 如何在日常开发中高效使用 Copilot
  • 无人机高科技,翱翔未来新天地
  • 对比学习与先验知识引导的特征提取网络在胶质瘤高风险复发区域预测中的应用|文献速递-深度学习人工智能医疗图像
  • GS-IR:3D 高斯喷溅用于逆向渲染
  • 2025年08月21日Github流行趋势
  • AI动画剧本、脚本、分镜头生成提示词
  • 【Flutter】Container设置对齐方式会填满父组件剩余空间