描述

  • 给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:
  • 1、查询A[i],A[i+1],A[i+2],...,A[j](1<=i<=j<=N)中,升序排列后排名第k的数。
  • 2、修改A[i]的值为j。

分析

  • 用了很长时间理解树状数组+主席树的做法
  • 这里先有一个正常的主席树, 保存无修改时的数据, 然后用树状数组维护一个记录增量的主席树, 维护的信息和普通树状数组一样, 也是是某一段内的数据. 比如修改了位置x的数据, 那么需要更新 x, x+lowbit(x)... 直到刚小于n 的数据
#include #include #include #include using namespace std;
const int maxnode = 3000000;
const int maxn = 60000 + 10;
const int maxm = 10000 + 10;
struct Question {
int a, b, c, k;
} qst[maxm];
int label;
int A[maxn], T[maxn];
int root[maxn<<1];
int s[maxnode], lc[maxnode], rc[maxnode];
#define q qst[i]
#define M (L+R>>1)
void build(int& x, int y, int L, int R, int v) {
x = ++label;
lc[x] = lc[y], rc[x] = rc[y], s[x] = s[y] + 1;
if(L == R) return;
if(v <= M) build(lc[x], lc[y], L, M, v);
else build(rc[x], rc[y], M+1, R, v);
}
void modify(int& x, int L, int R, int v, int d) {
if(!x) x = ++label;
s[x] += d;
if(L == R) return;
if(v <= M) modify(lc[x], L, M, v, d);
else modify(rc[x], M+1, R, v, d);
}
int main() {
freopen("dynrank.in", "r", stdin);
freopen("dynrank.out", "w", stdout);
int kase;
scanf("%d", &kase);
while(kase--) {
label = 0;
int n, m, tot = 0;
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", &A[i]);
T[++tot] = A[i];
}
char opt[2];
for(int i = 1; i <= m; i++) {
scanf("%s", opt);
if(opt[0] == 'Q') {
q.k = 0;
scanf("%d %d %d", &q.a, &q.b, &q.c);
} else {
q.k = 1;
scanf("%d %d", &q.a, &q.b);
T[++tot] = q.b;
}
}
sort(T+1, T+tot+1);
tot = unique(T+1, T+tot+1)-T-1;
for(int i = 1; i <= n; i++)
A[i] = lower_bound(T+1, T+tot+1, A[i])-T;
// 几个 memset 特别耗费时间, 可以巧妙地换掉
memset(root, 0, sizeof(root));
memset(s, 0, sizeof(s));
memset(lc, 0, sizeof(lc));
memset(rc, 0, sizeof(rc));
// 原始主席树占用空间 [n+1, n+n], 记录前缀和
// 记录增量占用空间 [1, n], 记录某个位置的增量
for(int i = 1; i <= n; i++)
build(root[i + n], root[i-1 + n], 1, tot, A[i]);
for(int i = 1; i <= m; i++)
if(q.k == 0) {
vectorq1, q2; int L = 1, R = tot, rk = q.c; // 答案区间 [L, R] if(q.a == 1) q1.push_back(root[0]); else q1.push_back(root[q.a-1 + n]); q2.push_back(root[q.b + n]); for(int x = q.a-1; x > 0; x -= (x&-x)) q1.push_back(root[x]); for(int x = q.b; x > 0; x -= (x&-x)) q2.push_back(root[x]); while(L < R) { int ls = 0; for(int x = 0; x < q1.size(); x++) ls -= s[lc[q1[x]]]; for(int x = 0; x < q2.size(); x++) ls += s[lc[q2[x]]]; if(rk <= ls) { for(int x = 0; x < q1.size(); x++) q1[x] = lc[q1[x]]; for(int x = 0; x < q2.size(); x++) q2[x] = lc[q2[x]]; R = M; } else { for(int x = 0; x < q1.size(); x++) q1[x] = rc[q1[x]]; for(int x = 0; x < q2.size(); x++) q2[x] = rc[q2[x]]; L = M + 1, rk -= ls; } } printf("%d\n", T[L]); } else { for(int x = q.a; x <= n; x += (x&-x)) modify(root[x], 1, tot, A[q.a], -1); A[q.a] = lower_bound(T+1, T+tot+1, q.b)-T; for(int x = q.a; x <= n; x += (x&-x)) modify(root[x], 1, tot, A[q.a], 1); } } return 0; } 

COGS-257-动态排名系统-树状数组+主席树相关推荐

  1. 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

    题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见-- 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...

  2. 线。段。树--树状数组-主席树

    简单了解一下线段树 以前写过的内容,搬运过来 线段树的应用场景:满足区间加法性质且多次查询,什么是区间加法性质,比如最大值,求和,树状数组.线段树.主席树依次. 线段树框架:建树--查询--更新... ...

  3. HDU 3333 Turing Tree(树状数组/主席树)

    题意 给定一个长度为 \(n​\) 的序列,\(m​\) 个查询,每次查询区间 \([L,R]​\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...

  4. hdu 4417 Super Mario 树状数组||主席树

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Prob ...

  5. 洛谷 - P2163 [SHOI2007]园丁的烦恼(不带修二维数点-树状数组/主席树)

    题目链接:点击查看 题目大意:二维平面坐标系中给出 nnn 个坐标点,然后是 mmm 次询问,每次询问需要回答一个闭合矩阵中有多少个点 题目分析:想挂树套树来着,但是复杂度有点大.本题不带修且可以离线 ...

  6. bzoj 1901: Zju2112 Dynamic Rankings(离线树状数组+主席树)

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 8144  Solved: 3378 [ ...

  7. [NOI Online 2022 提高组] 丹钓战(单调栈 + 树状数组 / 主席树)

    problem luogu-P8251 solution 按照题意模拟单调栈. 求出对于 iii 而言,当时单调栈的栈顶元素记为 pip_ipi​. 如果到 iii 时,栈顶已经为 pip_ipi​ ...

  8. D-query SPOJ - DQUERY(求区间不同数的个数)(树状数组||线段树+离散)(主席树+在线)

    English Vietnamese Given a sequence of n numbers a1, a2, -, an and a number of d-queries. A d-query ...

  9. 树状数组(树状数组的基本用法与操作)

    什么是树状数组?树状数组简单的来说就是将一个数组模拟树形结构. 树状数组有什么用?树状数组可以将求和的操作从O(n)操作简化为O(logn). 如图所示,横线下方为a数组表示为初试数据:上方为数组c, ...

最新文章

  1. XML之父从愤然亚马逊离职,放弃百万年薪,谷歌华为争抢
  2. linux中probe函数传递参数的寻找(下)
  3. MySQL 中一个双引号的错位引发的血案
  4. web前端技术分享Electron之Renderer Process API
  5. Cython与CPython的区别
  6. 我如何使用React和Typescript在freeCodeCamp中构建天气应用
  7. 程序员:站在“自学”鄙视链顶端的王者
  8. 大会门票限免最后一周!来聊聊 NVIDIA、抖音等大厂的 AI 技术落地
  9. SqlServer行转列
  10. 阿里布局无人驾驶;滴滴成立汽车服务;“京东 AI 天团”首亮相| CSDN极客头条
  11. java基础之测试类
  12. 2017数学建模B题回顾与解题分享
  13. SAP计划策略组详细介绍
  14. 《基因突变》学习笔记
  15. 同步/异步 异步回调 协成 线程队列
  16. 微型计算机电路试卷,微机原理试卷及答案2
  17. bim学习—— 第7章 放置幕墙门窗
  18. 弄懂这56个Python使用技巧,掌握Python高效开发
  19. HTML5 参考手册 ———— 颜色名
  20. java 打印表格文件

热门文章

  1. 云炬随笔20211010(4)
  2. 学长毕业日记 :本科毕业论文写成博士论文的神操作20160317
  3. 第15课:卷积神经网络(CNN)
  4. 北理工 管理系统计算机仿真作业,20秋北理工《CADCAM原理与应用》--模拟3-答案 更…...
  5. android 小球效果,Android开发实现跟随手指的小球效果示例
  6. Delphi自动提交网页表单和获取框架网页源码
  7. 在asp.net 中应用POST传递和接收XML文件以及参数.
  8. OpenGL从入门到精通--纹理
  9. 【CyberSecurityLearning 46】PHP 函数
  10. 您必须有下列压缩分卷才能继续解压