LuoguP2617 Dynamic Rankings (动态主席树学习理解)
题目地址
题解
动态主席树的板子题。动态主席树其实和静态的有很大差别,虽然同样是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 rc
int 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;
}
LuoguP2617 Dynamic Rankings (动态主席树学习理解)的更多相关文章
- P2617 Dynamic Rankings 动态主席树
\(\color{#0066ff}{ 题目描述 }\) 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i ...
- 【bzoj1901】Zju2112 Dynamic Rankings 离散化+主席树+树状数组
题目描述 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤ ...
- ZOJ 2112 Dynamic Rankings(主席树の动态kth)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2112 The Company Dynamic Rankings ...
- zoj2112 Dynamic Rankings (主席树 || 树套树)
The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with t ...
- luogu P2617 Dynamic Rankings(主席树)
嘟嘟嘟 一句话题意:带修改区间第\(k\)小. 不修改都会,主席树板子.但是有修改就要比较深入的理解主席树了. 众所周知,主席树中以\(i\)为根的线段树维护的是\([1, i]\)这个前缀的权值,因 ...
- 动态主席树【带修改】&& 例题 Dynamic Rankings ZOJ - 2112
参考链接:https://blog.csdn.net/WilliamSun0122/article/details/77885781 一.动态主席树介绍 动态主席树与静态主席树的不同在于:静态主席树不 ...
- bzoj1901&zoj2112&cogs257 Dynamic Rankings(动态排名系统)
bzoj1901&zoj2112&cogs257 Dynamic Rankings(动态排名系统) cogs zoj bzoj-权限 题解 bzoj和zoj都是骗访问量的233,我没有 ...
- 【BZOJ1901】【Luogu2617】Dynamic Ranking(主席树,树状数组)
[BZOJ1901][Luogu2617]Dynamic Ranking(主席树,树状数组) 题面 神TM BZOJ权限题 Luogu真良心 题解 如果不考虑修改 很容易的主席树区间第K大 考虑修改 ...
- 【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题
达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状 ...
随机推荐
- 如何让模拟的json数据接口能够正常的在手机上有效果
1. 确保手机与PC在同一个ip网下 这里我是通过------------360随身WIFI,20块钱淘宝上卖的,外观像U盘一样的,直接插在电脑的USB上就能在PC上创建一个WiFi,手机连接上就可以 ...
- 管理npm源命令
nrm ls 查看源镜像 nrm add 自定义名称 源地址 nrm use 自定义名称
- BIO, NIO 和 Epoll (转载)
很好的文章 https://eklitzke.org/blocking-io-nonblocking-io-and-epoll
- gdb调试android
手机端 adb shell gdbserver --mulit *:23333 /data/local/tmp/test 电脑 target remote 192.168.1.170:23333
- 从零开始一起学习SLAM | 点云到网格的进化
点击公众号"计算机视觉life"关注,置顶星标更快接收消息! 本文编程练习框架及数据获取方法见文末获取方式 菜单栏点击"知识星球"查看「从零开始学习SLAM」一 ...
- locust压测rpc协议
这里主要是google的grpc接口进行压测的一个栗子. Locust是以HTTP为主要目标构建的. 但是,通过编写钩子触发器request_success和 request_failure事件的自定 ...
- Unity 利用UGUI打包图集,动态加载sprite资源
今天做了一个UI界面,这个界面是好友界面,该界面上有若干个好友item. 需要对每个tem的头像对象(image)动态显示对应的头像.尝试利用UGUI的图集来加载,具体实现如下: 1.首先,需要知道S ...
- 腾讯笔试编程题,贪吃的小Q(二分查找)
问题描述 小Q的父母要出差N天,走之前给小Q留下了M块巧克力.小Q决定每天吃的巧克力数量不少于前一天吃的一半,但是他又不想在父母回来之前的某一天没有巧克力吃,请问他第一天最多能吃多少块巧克力. 输入描 ...
- intellij idea 官方帮助文档翻译(一)安装
安装需求: 硬件需求: 最低2GB内存,推荐4GB内存 最少要有1.5GB的硬盘空间,以及1GB空间用于缓存 最低1024*768的分辨率 软件需求: intellij idea中包含了jre 1.8 ...
- 为fastdfs文件服务器新增一个storage
一.前言: 前期,已经搭建好了一套fastdfs文件服务器,一个tracker和一个storage,且部署在同一台服务器上,已经正式投入运行快半年了,1T的空间现在只剩下100G容量了,现在需要扩容, ...