题目地址

题目链接

题解

动态主席树的板子题。动态主席树其实和静态的有很大差别,虽然同样是n个根,但是节点并不能共用,每个根节点表示bit上的一段区间。
所以其实是个树套树的东西来着,外层是bit,内层是主席树。
然后将所有数离散(包括读入进来的修改的数,所以动态主席树其实是离线的),那么就映射成了一段连续区间,用主席树维护这段区间。
每次修改就把x->n(+=lowbit(x))的所有节点的数v的那条链加上v,注意动态开点,不然空间爆炸。这样子 空间就是 \(nlog^2n\)的(每次修改只会动到一条链,一共动log条,所以是\(log^2\)的)。可以看一下下面这个图,很形象。

(图片来源于Flash_Hu)
每次查询将l-1和r两个点的前缀和在bit上面对应的节点找出来(log个),然后在主席树上向下走,一次同时减l-1对应的log个主席树,同时加r对应的log个主席树
这样子时间复杂度是\(O(nlog^2n)\)。
大概就是这样...然后查询可以写成类似二分的写法,就可以非递归找了。但是修改还是写成递归的靠谱一点(非递归要写指针,指针容易写挂..)。还有注意每次修改要修改的是离散化后的值,但是输出要输出离散前的。
再看个代码意会一下应该就没问题了...

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200100, M = 40000100;int a[N], b[N], len;
int l[N], r[N], op[N], d[N];
int n, m, root[N], rootl[30], rootr[30], tot;
struct tree {int lc, rc, sum;
}t[M];#define lowbit(i) (i&(-i))
void upd_tree(int &rt, int l, int r, int pos, int v) {if(!rt) rt = ++tot; t[rt].sum += v;if(l == r) return;int mid = (l + r) >> 1;if(pos <= mid) upd_tree(t[rt].lc, l, mid, pos, v);else upd_tree(t[rt].rc, mid + 1, r, pos, v);
}void upd(int pos, int k, int v) {for(int i = pos; i <= n; i += lowbit(i)) {upd_tree(root[i], 1, len, k, v);}
}
#define lc(i) (t[i].lc)
#define rc(i) (t[i].rc)
int query(int L, int R, int k) {int sum = 0, cur_l = 0, cur_r = 0;for(int i = L - 1; i; i -= lowbit(i)) rootl[++cur_l] = root[i];for(int i = R; i; i -= lowbit(i)) rootr[++cur_r] = root[i];int l = 1, r = len;while(l != r) {int mid = (l + r) >> 1; sum = 0;for(int i = 1; i <= cur_r; ++i) sum += t[lc(rootr[i])].sum;for(int i = 1; i <= cur_l; ++i) sum -= t[lc(rootl[i])].sum;if(k <= sum) {r = mid;for(int i = 1; i <= cur_l; ++i) rootl[i] = lc(rootl[i]);for(int i = 1; i <= cur_r; ++i) rootr[i] = lc(rootr[i]);}else {l = mid + 1, k -= sum;for(int i = 1; i <= cur_l; ++i) rootl[i] = rc(rootl[i]);for(int i = 1; i <= cur_r; ++i) rootr[i] = rc(rootr[i]);}}return b[l];
}
#undef lc
#undef rcint main() {scanf("%d%d", &n, &m);for(int i = 1; i <= n; ++i) scanf("%d", &a[i]), b[++len] = a[i];for(int i = 1; i <= m; ++i) {char ch[5];scanf("%s%d%d", ch, &l[i], &r[i]);op[i] = ch[0] == 'Q';if(op[i]) scanf("%d", &d[i]);else b[++len] = r[i];}sort(b+1,b+len+1); len = unique(b+1,b+len+1)-b-1;for(int i = 1; i <= n; ++i) a[i] = lower_bound(b+1,b+len+1,a[i])-b;for(int i = 1; i <= n; ++i) upd(i, a[i], 1);for(int i = 1; i <= m; ++i) {if(!op[i]) {upd(l[i], a[l[i]], -1);a[l[i]] = lower_bound(b+1,b+len+1,r[i])-b;upd(l[i], a[l[i]], 1);} else {printf("%d\n", query(l[i], r[i], d[i]));}}return 0;
}

转载于:https://www.cnblogs.com/henry-1202/p/10684627.html

LuoguP2617 Dynamic Rankings (动态主席树学习理解)相关推荐

  1. P2617 Dynamic Rankings 动态主席树

    \(\color{#0066ff}{ 题目描述 }\) 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...

  2. ZOJ 2112 Dynamic Rankings(主席树-动态第k大)

    Description 给出一个长度为n的序列a,两种操作 C x v:将第x个元素的值改成v Q l r k:查询区间[l,r]中第k大的元素 Input 第一行为一个整数t表示用例组数,每组用例第 ...

  3. P2617 Dynamic Rankings(主席树+树状数组)

    怕是还没有题解,所以先写一篇. 这题就是维护带修改的主席树.首先树套树肯定是能做的,既然树套树能做那么整体二分肯定也是可以的. 由于我并没有使用这两种做法,所以此处不予介绍. 大概描述下主席树的思路: ...

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

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

  5. P2617 Dynamic Rankings 动态区间第K大【树套树】或【整体二分】

    传送门 动态区间第KKK大问题,单点修改(这里是第kkk小,即是从小到大第kkk个) 这里还有个区间修改,有点类似的 P3332 [ZJOI2013]K大数查询 分析 树套树 树套树,就是用一种树形结 ...

  6. 树套树 ---- 树状数组套权值线段树模板题 P2617 Dynamic Rankings 动态第K大

    题目链接 题目大意: 给你一个数组aaa,aaa有两个操作 询问aaa中[l,r][l,r][l,r]区间里面第kkk小的数是哪个? 修改axa_xax​为yyy 解题思路: 首先我们知道权值线段树是 ...

  7. BZOJ-1901 Zju2112 Dynamic Rankings 函数式线段树 套 树状数组+离线处理

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MB Submit: 6058 Solved: 2521 [Su ...

  8. 主席树学习小结(POJ 2104)

    在高中的时候就听到过主席树了,感觉非常高端,在寒假的时候 winter homework中有一题是查找区间第K大的树,当时就开始百度这种网上的博客,发现主席树看不懂,因为那个root[i],还有tx[ ...

  9. BZOJ 1901 Dynamic Rankings(线段树+treap)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1901 题意:给出一个数列,两种操作:(1)询问区间第K小值:(2)修改某个位置的值. 思 ...

最新文章

  1. JS简单实现自定义右键菜单
  2. 使用程序解决一道逻辑推理题
  3. Can‘t connect to local MySQL server through socket ‘/home/mysql/mysql-5.6.33/mysql.sock
  4. 关于Delphi中DLL,BPL等无法调试的问题
  5. 【深度学习】深度学习之LSTM
  6. C++ 枚举类型详解
  7. 【算法分析与设计】查找第K大/小元素问题
  8. Fedora16 下更改多系统、多内核的默认启动项
  9. 查找重复文件_快速查找、删除重复图片及文件!
  10. 2019.7.23整理记录以及四道题
  11. 二十二、Oracle学习笔记:Oracle异常
  12. java图书管理系统代码_java图书管理系统(源码+jar包+数据库)
  13. 简单数独的DFS求解
  14. HTTP报文结构详解
  15. c语言小饭店等位就餐程序,小饭店预约登记管理系统,
  16. 河南省赛 导弹发射 lis
  17. 生成计算机组成原理:8位算术逻辑运算实验数据
  18. 模块“XXX.dll”加载失败
  19. 周志明论架构之道:从SOA时代到微服务时代
  20. 《千面英雄》听书笔记

热门文章

  1. solr 3.5 配置及服务器设置
  2. openoj的一个小比赛(F题解题报告)poj3978(dp+素数筛选)
  3. 【Socket研究】~。~ Scoket开发蛋疼笔记 Silverlight
  4. 非常认同的《SEO优化大全》
  5. php常用20函数,PHP常用函数
  6. pat 多项式A/B
  7. mysql 写入400_MySQL5.7运行CPU达百分之400处理方案
  8. mysql不同实例数据同步_两台Mysql数据库数据同步实现实例
  9. cascader 动态加载 回显_ElementUI cascader级联动态加载回显和搜索看这个就够了
  10. mysql smack_super-smack测试mysql性能