ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改
思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高。那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出权值线段树前缀和,相减就是区间前缀和。而且我维护也只要改logn棵树就好了。具体看JQ博客。
代码:
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 5e4 + ;
const int M = maxn * ;
const ull seed = ;
const int INF = 0x3f3f3f3f;
const int MOD = ;
int a[maxn], root[maxn], tot;
int sroot[maxn]; //树状数组的头
int use[maxn]; //保存树状数组的头
int n, m, L, R;
vector<int> vv;
struct node{
int lson, rson;
int sum;
}T[maxn * ];
struct Que{
int order;
int l, r, k;
}q[maxn];
void init(){
memset(T, , sizeof(T));
memset(sroot, , sizeof(root));
tot = ;
vv.clear();
}
int lowbit(int x){
return x&(-x);
}
int getId(int x){
return lower_bound(vv.begin(), vv.end(),x) - vv.begin() + ;
}
void update(int l, int r, int &now, int pre, int v, int pos){
T[++tot] = T[pre], T[tot].sum += v, now = tot;
if(l == r) return;
int m = (l + r) >> ;
if(pos <= m)
update(l, m, T[now].lson, T[pre].lson, v, pos);
else
update(m + , r, T[now].rson, T[pre].rson, v, pos);
}
int add(int x, int v, int pos){
for(int i = x; i <= n; i += lowbit(i)){
update(, vv.size(), sroot[i], sroot[i], v, pos);
}
}
int SUM(int pos){
int ret = ;
for(int i = pos; i > ; i -= lowbit(i))
ret += T[T[use[i]].lson].sum;
return ret;
} int query(int l, int r, int now, int pre, int k){
if(l == r) return l;
int sum = SUM(R) - SUM(L) + T[T[now].lson].sum - T[T[pre].lson].sum;
int m = (l + r) >> ;
if(sum >= k){
for(int i = R; i > ; i -= lowbit(i)) use[i] = T[use[i]].lson;
for(int i = L; i > ; i -= lowbit(i)) use[i] = T[use[i]].lson;
return query(l, m, T[now].lson, T[pre].lson, k);
}
else{
for(int i = R; i > ; i -= lowbit(i)) use[i] = T[use[i]].rson;
for(int i = L; i > ; i -= lowbit(i)) use[i] = T[use[i]].rson;
return query(m + , r, T[now].rson, T[pre].rson, k - sum);
}
} int main(){
int T;
scanf("%d", &T);
while(T--){
init();
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++){
scanf("%d", &a[i]);
vv.push_back(a[i]);
}
for(int i = ; i <= m; i++){
char o[];
scanf("%s", o);
if(o[] == 'Q'){
q[i].order = ;
scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].k);
}
else{
q[i].order = ;
scanf("%d%d", &q[i].l, &q[i].k);
vv.push_back(q[i].k);
}
} sort(vv.begin(), vv.end());
vv.erase(unique(vv.begin(), vv.end()), vv.end()); for(int i = ; i <= n; i++){
update(, vv.size(), root[i], root[i - ], , getId(a[i]));
}
for(int i = ; i <= m; i++){
if(q[i].order == ){
L = q[i].l - , R = q[i].r;
for(int j = R; j > ; j -= lowbit(j)) use[j] = sroot[j];
for(int j = L; j > ; j -= lowbit(j)) use[j] = sroot[j];
printf("%d\n", vv[query(, vv.size(), root[R], root[L], q[i].k) - ]);
}
else{
add(q[i].l, -, getId(a[q[i].l]));
a[q[i].l] = q[i].k;
add(q[i].l, , getId(a[q[i].l]));
}
}
}
return ;
}
ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解的更多相关文章
- P2617 Dynamic Rankings(树状数组套主席树)
P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...
- BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树
[题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...
- LUOGU P2617 Dynamic Rankings(树状数组套主席树)
传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...
- BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树
[题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...
- BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树
BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...
- [COGS257]动态排名系统 树状数组套主席树
257. 动态排名系统 时间限制:5 s 内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...
- BZOJ 2141 排队(树状数组套主席树)
解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...
- 洛谷P3759 [TJOI2017]不勤劳的图书管理员 【树状数组套主席树】
题目链接 洛谷P3759 题解 树状数组套主席树板题 #include<algorithm> #include<iostream> #include<cstring> ...
- Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...
随机推荐
- jar包通过exe4j打包成exe可执行文件
https://blog.csdn.net/jia611/article/details/42060945 参照此文即可,注意,我的是maven打包成的jar,选择maincalss时,需要选择jar ...
- c++第三次实验
第一题: 先把代码贴上来 main.cpp #include <iostream> #include <cstdlib> #include<conio.h> #in ...
- python webbrowser模块(浏览器操作)
webbrowser模块提供了一个高级接口来显现基于Web的文档,大部分情况下只需要简单的调用open()办法. webbrowser定义了如下的反常: exception webbrowser.Er ...
- 【Python全栈-CSS】CSS实现网页背景图片自适应全屏
CSS实现网页背景图片自适应全屏 功能:实现能自适应屏幕大小又不会变形的背景大图,而且背景图片不会随着滚动条滚动而滚动. 以下是用CSS实现的方法: <html> <head> ...
- HotSpot设计原理与实现:一、初识HotSpot
一.HotSpot内核模块组成和功能框架 1.HotSpot内核模块图 (1)Prims模块: (2)Service模块: (3)Runtime模块: 二.虚拟机生命周期(JVM初始化过程) 1.虚拟 ...
- JMS笔记(三)
最近重看activemq,对消息的传送确认机制有了进一步认识 1. mq在确认consumer收到消息后才会删除消息,因此consumer接收消息后应该进行ack"确认",java ...
- Linux 下如何修改用户名(同时修改用户组名和家目录)
有时候,由于某些原因,我们可能会需要重命名用户名.我们可以很容易地修改用户名以及对应的家目录和 UID.-- Shusain 本文导航◈ 修改用户名12%◈ 修改家目录43%◈ 更改用户 UID52% ...
- python函数带()与否
一.不带括号时,调用的是这个函数本身 ,是整个函数体,是一个函数对象,不须等该函数执行完成二.带括号(参数或者无参),调用的是函数的执行结果,须等该函数执行完成的结果 进程和线程的target=fun ...
- vi命令复制粘贴
2.复制粘贴 yy :复制当前行 p :粘贴到光标所在行的下一行
- 表情的战争(App名称)技术服务支持
1.进入游戏走过场动画,可以点击退出跳过此过场动画: 2.进入主界面后直接点击开始游戏进入场景跑图,进入npc对话面板,对话结束进入战斗面板: 3.战斗操作方法为玩家拖动表情牌,进行攻击或者防守,直至 ...