Dynamic Rankings代码

主要是记录一下整体二分的板子

#include <cstdio> #include <algorithm> using namespace std; #define MAXN 100000 struct element {//修改 int loc; int time;//时间戳 int value; int com; element (){} element (int loc1, int time1, int value1, int com1) { loc = loc1; time = time1; value = value1; com = com1; } }se[MAXN * 3 + 5], teme[MAXN * 3 + 5]; int End = 0; struct question {//询问 int num; int l, r; int k; int time;//时间戳 question (){} question (int num1, int l1, int r1, int k1, int time1) { num = num1; l = l1; r = r1; k = k1; time = time1; } }sq[MAXN + 5], temq[MAXN + 5]; int num = 0; bool vis[MAXN + 5]; int BIT[MAXN + 5];//单点修改, 区间查询通过BIT来实现 int snow[MAXN + 5];//每次修改需要先删除这个位置上一次的值, 再添加新的值, 所以用一个数组存 int answer[MAXN + 5];//答案 int lowbit (int i) { return i & (-i); } void change (int l, int v) { for (int i = l; i <= MAXN; i += lowbit (i)) { BIT[i] += v; } } int Sum (int l){ int ans = 0; for (int i = l; i; i ^= lowbit (i)) { ans += BIT[i]; } return ans; } int ask (int l, int r) { return Sum (r) - Sum (l - 1); } void dichotomy (int le, int re, int lq, int rq, int vl, int vr) { if (vl == vr) {//如果二分到底了, 就直接是答案了 for (int i = lq; i <= rq; i ++) { answer[sq[i].num] = vl; } return ; } int mid = (vl + vr) >> 1; int ie = le, iq = lq; for (int i = lq; i <= rq; i ++) {//相当于普通二分中check的0, 1 vis[i] = 0; } while (ie <= re && iq <= rq) { if (se[ie].time <= sq[iq].time) {//时间戳来判断操作先后 change (se[ie].loc, (se[ie].value <= mid) * se[ie].com); ie ++; } else { int sum = ask (sq[iq].l, sq[iq].r); vis[iq] = (sum >= sq[iq].k); if (!vis[iq]) { sq[iq].k -= sum;//分到mid右边后要将左边修改的贡献提前算上好 } iq ++; } } while (iq <= rq) { int sum = ask (sq[iq].l, sq[iq].r); vis[iq] = (sum >= sq[iq].k); if (!vis[iq]) { sq[iq].k -= sum; } iq ++; } for (int i = le; i < ie; i ++) {//将BIT清0 change (se[i].loc, -(se[i].value <= mid) * se[i].com); } //将询问和修改都按照mid分为左右两边 int ne = le - 1; for (int i = le; i <= re; i ++) { if (se[i].value <= mid) { teme[++ ne] = se[i]; } } for (int i = le, j = ne; i <= re; i ++) { if (se[i].value > mid) { teme[++ j] = se[i]; } } for (int i = le; i <= re; i ++) { se[i] = teme[i]; } int nq = lq - 1; for (int i = lq; i <= rq; i ++) { if (vis[i]) { temq[++ nq] = sq[i]; } } for (int i = lq, j = nq; i <= rq; i ++) { if (!vis[i]) { temq[++ j] = sq[i]; } } for (int i = lq; i <= rq; i ++) { sq[i] = temq[i]; } if (nq >= lq) { dichotomy (le, ne, lq, nq, vl, mid); } if (nq < rq) { dichotomy (ne + 1, re, nq + 1, rq, mid + 1, vr); } } int main () { int n, m; scanf ("%d %d", &n, &m); for (int i = 1; i <= n; i ++) { scanf ("%d", &snow[i]); se[++End] = element (i, 0, snow[i], 1); } for (int i = 1; i <= m; i ++) { char opt = getchar (); while (opt > 'Z' || opt < 'A') { opt = getchar (); } if (opt == 'Q') { int l, r, k; scanf ("%d %d %d", &l, &r, &k); ++num; sq[num] = question (num, l, r, k, i); } else if (opt == 'C') { int l; int v; scanf ("%d %d", &l, &v); se[++End] = element (l, i, snow[l], -1); snow[l] = v; se[++End] = element (l, i, snow[l], 1); } }; dichotomy (1, End, 1, num, 0, 1e9); for (int i = 1; i <= num; i ++) { printf ("%d\n", answer[i]); } }

__EOF__

本文作者FlowerDream
本文链接https://www.cnblogs.com/flower-dream/p/Answer_Dynamic_Rankings.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   小篪篪  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
Live2D
欢迎阅读『Dynamic Rankings代码』
点击右上角即可分享
微信分享提示