BZOJ 1901 Zju2112 Dynamic Rankings 树状数组套线段树
题意概述:带修改求区间第k大。
分析:
我们知道不带修改的时候直接上主席树就可以了对吧?两个版本号里面的节点一起走在线段树上二分,复杂度是O((N+M)logN)。
然而这里可以修改,主席树显然是凉了,但是注意到主席树的不带修改做法实际上是利用的差分的性质,即主席树本身实际上就是维护的一个前缀和一样的东西。想想普通的前缀和问题,我们求带修改前缀和是怎么做的?树状数组!于是我们用树状数组套线段树,树状数组里面每个点是一棵权值线段树,维护的是位置i前面lowbit(i)范围中的元素的权值信息,每一次更新的时候在logN棵线段树里修改,询问的时候logN棵线段树里一起走,在线段树上二分(树状数组套在外面写起来简单)。
由于这个题对时间效率要求不是很高我就直接动态开点了没有离散化也没有卡常。实际上就是我比较懒
时间复杂度O((N+M)logN^2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
const int maxn=;
const int up=; int N,M,a[maxn];
struct mstruct{
static const int maxnode=;
static const int maxl=;
int rt[maxl],np,lc[maxnode],rc[maxnode],sz[maxnode];
int q1[maxl],q2[maxl],l1,l2;
mstruct(){ np=,sz[]=; memset(rt,,sizeof(rt)); }
int lowbit(int i){ return i&(-i); }
void pushup(int now){ sz[now]=sz[lc[now]]+sz[rc[now]]; }
void inupdate(int &now,int L,int R,int p,int v){
if(!now) now=++np,lc[now]=rc[now]=sz[now]=;
if(L==R){ sz[now]+=v; return; }
int m=L+R>>;
if(p<=m) inupdate(lc[now],L,m,p,v);
else inupdate(rc[now],m+,R,p,v);
pushup(now);
}
void update(int p,int v,bool c){
int i=p;
while(i<=N){
if(c) inupdate(rt[i],,up,a[p],-);
inupdate(rt[i],,up,v,);
i+=lowbit(i);
}
a[p]=v;
}
void mov(bool rig){
for(int i=;i<l1;i++) q1[i]=rig?rc[q1[i]]:lc[q1[i]];
for(int i=;i<l2;i++) q2[i]=rig?rc[q2[i]]:lc[q2[i]];
}
int inquery(int L,int R,int k){
if(L==R) return L;
int m=L+R>>,s1=,s2=;
for(int i=;i<l1;i++) s1+=sz[lc[q1[i]]];
for(int i=;i<l2;i++) s2+=sz[lc[q2[i]]];
if(k<=s2-s1){ mov(); return inquery(L,m,k); }
mov(); return inquery(m+,R,k-(s2-s1));
}
int query(int L,int R,int k){
l1=l2=;
int i=L; while(i) q1[l1++]=rt[i],i-=lowbit(i);
i=R; while(i) q2[l2++]=rt[i],i-=lowbit(i);
return inquery(,up,k);
}
}tt; void data_in()
{
scanf("%d%d",&N,&M);
for(int i=;i<=N;i++) scanf("%d",&a[i]);
for(int i=;i<=N;i++) tt.update(i,a[i],);
}
void work()
{
char op[];
int l,r,k,t;
for(int i=;i<=M;i++){
scanf("%s",op);
if(op[]=='C'){
scanf("%d%d",&l,&t);
tt.update(l,t,);
}
else if(op[]=='Q'){
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",tt.query(l-,r,k));
}
}
}
int main()
{
data_in();
work();
return ;
}
BZOJ 1901 Zju2112 Dynamic Rankings 树状数组套线段树的更多相关文章
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】
题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...
- BZOJ.4553.[HEOI2016&TJOI2016]序列(DP 树状数组套线段树/二维线段树(MLE) 动态开点)
题目链接:BZOJ 洛谷 \(O(n^2)\)DP很好写,对于当前的i从之前满足条件的j中选一个最大值,\(dp[i]=d[j]+1\) for(int j=1; j<i; ++j) if(a[ ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- [APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树)
[APIO2019] [LOJ 3146] 路灯 (cdq分治或树状数组套线段树) 题面 略 分析 首先把一组询问(x,y)看成二维平面上的一个点,我们想办法用数据结构维护这个二维平面(注意根据题意这 ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- bzoj3196 二逼平衡树 树状数组套线段树
题目传送门 思路:树状数组套线段树模板题. 什么是树状数组套线段树,普通的树状数组每个点都是一个权值,而这里的树状数组每个点都是一颗权值线段树,我们用前缀差分的方法求得每个区间的各种信息, 其实关键就 ...
- 【序列操作IV】树状数组套线段树/树套树
题目描述 给出序列 a1,a2,…,an(0≤ai≤109),有关序列的两种操作. 1. ai(1≤i≤n)变成 x(0≤x≤109). 2. 求 al,al+1,…,ar(1≤l≤r≤n)第 k(1 ...
- 2019南昌网络赛 I. Yukino With Subinterval 树状数组套线段树
I. Yukino With Subinterval 题目链接: Problem Descripe Yukino has an array \(a_1, a_2 \cdots a_n\). As a ...
随机推荐
- 纯javascript实现选择框的全选与反选
HTML部分 <div id="wrap_input_box" > <input type="checkbox"><br> ...
- 建立复数类Complex,并且进行赋值,求和,取模等操作
#include "pch.h" #include <iostream> #include<cmath> using namespace std; clas ...
- linux下安装protobuf及cmake编译
一.protobuf 安装 protobuf版本:2.6.1 下载地址:https://github.com/google/protobuf/archive/v2.6.1.zip 解压之后进入目录 修 ...
- linux脚本运行错误:$'ls\r': command not found
原因在于 windows 下的换行符是 \r\n,而 linux 下的换行符是 \n 解决方案: 首先运行如下命令安装 dos2unix: yum install dos2unix -y 接下来运行如 ...
- Python 正则:前后界定和前后非界定
在用正则去匹配识别手机号.QQ.微信号的时候,往往由于输入的文本可能非常的另类,比如,没有标点和隔断,这时`^`和`$`就用不上了. 不用其实也可以识别的,但是有个问题,手机后是11位数字,QQ是5~ ...
- 手动封装一个属于自己的AJAX类库
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 《Linux命令学习手册》系列分享专栏
<Linux命令学习手册>系列分享专栏 <Linux命令学习手册>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read/207 ...
- Websocket 临时参考网站
https://blog.csdn.net/SGuniver_22/article/details/74273839 https://www.zhihu.com/question/20215561 h ...
- opencv+python视频实时质心显示
利用opencv+python实现以下功能: 1)获取实时视频,分解帧频: 2)将视频做二值化处理: 3) 将视频做滤波处理(去除噪点,获取准确轮廓个数): 4)识别图像轮廓: 5)计算质心: 6)描 ...
- 【 C 】字符串常量
当一个字符串常量出现在表达式中时,它的值是个指针常量.编译器把这些指定字符的一份拷贝存储在内存的某个位置,并存储一个指向第一个字符的指针.但是,当数组名用于表达式中时,它们的值也是个指针常量.我们可以 ...