【bzoj1901】dynamic ranking(带修改主席树/树套树)
题面地址(权限题)
首先说说怎么搞带修改主席树?
回忆一般的kth问题,我们的主席树求的是前缀和,这样我们在目标区间的左右端点的主席树差分下就能求出kth。
那么我们如何支持修改操作?
考虑到我们之前使用主席树朴素的维护区间前缀和,支持修改的话,只要把前缀和交给擅长它的树状数组维护,主席树只要维护下大概位置就好。
当然维护位置最好要离散化一下。我校某高傲的dalao直接写CTSC那道树上动态Kth,并且niubi地手写哈希维护。

别问我了在我写这篇文章的时候他还在debug呢。
由于我比较菜,只能先把这个区间的写了,并且我太菜只能lower_bound和unique……
代码学习的网上dalao以及hzwer。
#include<bits/stdc++.h>
#define N 10005
using namespace std;
inline int lowbit(int x){return x&-x;}
int n,m,sz,totn,totx,toty,a[N],b[N<<],ca[N],cb[N],cc[N];
int xx[N],yy[N],rt[N],size[*N],ls[*N],rs[*N];
void ins(int &o,int l,int r,int x,int q,int v){
o=++sz;size[o]=size[x]+v;ls[o]=ls[x];rs[o]=rs[x];
if(l==r)return;int mid=(l+r)>>;
if(q<=mid)ins(ls[o],l,mid,ls[x],q,v);
else ins(rs[o],mid+,r,rs[x],q,v);
}
int query(int l,int r,int q){
if(l==r)return l;
int sum=,mid=(l+r)>>;
for(int i=;i<=totx;i++)sum-=size[ls[xx[i]]];
for(int i=;i<=toty;i++)sum+=size[ls[yy[i]]];
if(q<=sum){
for(int i=;i<=totx;i++)xx[i]=ls[xx[i]];
for(int i=;i<=toty;i++)yy[i]=ls[yy[i]];
return query(l,mid,q);
}
else{
for(int i=;i<=totx;i++)xx[i]=rs[xx[i]];
for(int i=;i<=toty;i++)yy[i]=rs[yy[i]];
return query(mid+,r,q-sum);
}
}
void add(int x,int v){
int k=lower_bound(b+,b+totn+,a[x])-b;
for(int i=x;i<=n;i+=lowbit(i))ins(rt[i],,totn,rt[i],k,v);
}
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
int main(){char s[];
n=read();m=read();
for(int i=;i<=n;i++)a[i]=read(),b[++totn]=a[i];
for(int i=;i<=m;i++){
scanf("%s",s);ca[i]=read();cb[i]=read();
if(s[]=='Q')cc[i]=read();else b[++totn]=cb[i];
}
sort(b+,b+totn+);
totn=unique(b+,b+totn+)-b-;
for(int i=;i<=n;i++)add(i,);
for(int i=;i<=m;i++){
if(cc[i]){
totx=toty=;
for(int j=ca[i]-;j;j-=lowbit(j))xx[++totx]=rt[j];
for(int j=cb[i];j;j-=lowbit(j))yy[++toty]=rt[j];
printf("%d\n",b[query(,totn,cc[i])]);
}
else{add(ca[i],-);a[ca[i]]=cb[i];add(ca[i],);}
}
}
啊当然树套树也是可以的啦。
#include<bits/stdc++.h>
#define N 200001
#define M 1300001
#define inf 1000000007
using namespace std;
int n,m,tmp,a[N>>],rt[N],sz,size[M],ls[M],rs[M],val[M],w[M],rnd[M];
inline void pushup(int x){
//in Treap
size[x]=size[ls[x]]+size[rs[x]]+w[x];
}
void rturn(int &k)
{int t=ls[k];ls[k]=rs[t];rs[t]=k;size[t]=size[k];pushup(k);k=t;}
void lturn(int &k)
{int t=rs[k];rs[k]=ls[t];ls[t]=k;size[t]=size[k];pushup(k);k=t;}
void ins(int &k,int x){// in Treap
if(!k){
k=++sz;size[k]=;w[k]=;ls[k]=;rs[k]=;rnd[k]=rand();val[k]=x;return;
}
size[k]++;if(val[k]==x)w[k]++;
else if(x<val[k]){ins(ls[k],x);if(rnd[ls[k]]<rnd[k])rturn(k);}
else{ins(rs[k],x);if(rnd[rs[k]]<rnd[k])lturn(k);}
}
void del(int &k,int x){// in Treap
if(val[k]==x){
if(w[k]>){w[k]--;size[k]--;return;}
if(ls[k]*rs[k]==)k=ls[k]+rs[k];
else if(rnd[ls[k]]<rnd[rs[k]]){rturn(k);del(k,x);}
else{lturn(k);del(k,x);}
}
else if(x<val[k]){del(ls[k],x);size[k]--;}
else{del(rs[k],x);size[k]--;}
} void change(int o,int l,int r,int q,int num,int v){
// in Segment Tree
del(rt[o],v);ins(rt[o],num);
if(l==r)return;
int mid=(l+r)>>;
if(q<=mid)change(o<<,l,mid,q,num,v);
else change(o<<|,mid+,r,q,num,v);
}
void build(int o,int l,int r,int q,int num){
ins(rt[o],num);if(l==r)return;
int mid=(l+r)>>;
if(q<=mid)build(o<<,l,mid,q,num);
else build(o<<|,mid+,r,q,num);
}
void find(int k,int x){
if(!k)return;
if(val[k]<=x){tmp+=size[ls[k]]+w[k];find(rs[k],x);}
else find(ls[k],x);
}
void query(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){find(rt[o],v);return;}
int mid=(l+r)>>;
if(ql<=mid)query(o<<,l,mid,ql,qr,v);
if(qr>mid)query(o<<|,mid+,r,ql,qr,v);
}
inline int read(){
int f=,x=;char ch;
do{ch=getchar();if(ch=='-')f=-;}while(ch<''||ch>'');
do{x=x*+ch-'';ch=getchar();}while(ch>=''&&ch<='');
return f*x;
}
char s[];
int main(){
int T=read();
while(T--){
memset(rt,,sizeof(rt));sz=;
n=read();m=read();
for(int i=;i<=n;i++)a[i]=read();
for(int i=;i<=n;i++)build(,,n,i,a[i]);
for(int i=;i<=m;i++){
scanf("%s",s);
if(s[]=='C'){
int x=read(),y=read();
change(,,n,x,y,a[x]);
a[x]=y;
}
else{
int x=read(),y=read(),z=read();
int l=,r=inf;
while(l<=r){
int mid=(l+r)>>;
tmp=;query(,,n,x,y,mid);
if(tmp>=z)r=mid-;else l=mid+;
}
printf("%d\n",l);
}
}
}
return ;
}
其实这个树套树只要分清楚维护范围,也不是很难写的那种。
不过对于这种恶心的数据结构题,整体二分也是可以做到的。
这里是will大爷写的整体二分的题解。

【bzoj1901】dynamic ranking(带修改主席树/树套树)的更多相关文章
- BZOJ 1901: Zju2112 Dynamic Rankings | 带修改主席树
题目: emmmm是个权限题 题解: 带修改主席树的板子题,核心思想是用树状数组维护动态前缀和的性质来支持修改 修改的时候修改类似树状数组一样进行logn个Insert 查询的时候同理,树状数组的方法 ...
- Luogu Dynamic Ranking (带修改的主席树)
题目大意: 网址:https://www.luogu.org/problemnew/show/2617 给定一个序列a[1].a[2].....a[N],完成M个操作,操作有两种: [1]Q i j ...
- BZOJ1901 Dynamic Rankings|带修主席树
题目链接:戳我 其实我并不会做,于是看了题解 我们都知道主席树是利用前缀和记录历史版本来搞区间K大的一种数据结构.不过一般的主席树只能搞定静态区间第K大.如果带修怎么办呢? 想一下...单点修改+区间 ...
- 少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小
少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写 ...
- [BZOJ3295] [Cqoi2011]动态逆序对(带修改主席树)
题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序 ...
- BZOJ 1146: [CTSC2008]网络管理Network 带修改主席树_树套树_DFS序
Description M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路 ...
- 【bzoj1901】dynamic ranking(带修改主席树)
传送门(权限) 传送门(非权限) 花了一晚上总算把代码调好了……才知道待修改主席树怎么操作…… 然而还是一知半解orz…… 先说说我的理解吧 我们一般建主席树的时候都是直接在序列上建的 但是如果有修改 ...
- BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】
1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 7143 Solved: 2968[Su ...
- [luogu P2617] Dynamic Rankings 带修主席树
带修改的主席树,其实这种,已经不能算作主席树了,因为这个没有维护可持久化的... 主席树直接带修改的话,由于这种数据结构是可持久化的,那么要相应改动,这个节点以后所有的主席树,这样单次修改,就达到n* ...
随机推荐
- Java8的Stream流(一) --- 基础用法
Java8中的Stream Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象. Stream的特性及优点: 无存储. Stream不是一种数据 ...
- SDL源码阅读笔记(2) video dirver的初始化及选择
write by 九天雁翎(JTianLing) -- blog.csdn.net/vagrxie 前一篇文章 讲了SDL的除video以外的大部分模块.本文主要关注SDL的video模块部分. SD ...
- 深入理解JVM结构
JVM结构探究---- 1.JVM结构示意图 2.JVM运行时数据区 1)程序计数器(Program Counter Register) 程序计数器是用于存储每个线程下一步将执行的JVM指令,如该方法 ...
- 转载:OSG::Quat(四元数)用法
转自:http://blog.163.com/dj_zone/blog/static/4908931320098294047820/ osg::Quat To set the attitude of ...
- 洛谷P3230 比赛
emmmmmm,这个之前讲课的原题居然出到比赛里了. 我怒肝2h+然后A了此题,结果还是被某高一巨佬吊打...... 题意:n个球队两两比赛,胜得3分,败得0分,平得1分. 现有一个总分表,求问可能的 ...
- display position 和float的作用和关系
1.传统布局由这三者构成. 2.position设为absolute,那么display一定是block,因此对于span来说,就可以设置高和宽了. 3.position为relative ,那么fl ...
- npm install 报错Unexpected end of JSON input while parsing near...
安装node http://nodejs.cn/download/ 克隆代码 ....... 执行安装 npm install 然后就报了一坨错误 清理一下缓存 sudo npm cache veri ...
- 斯坦福大学公开课机器学习:梯度下降运算的特征缩放(gradient descent in practice 1:feature scaling)
以房屋价格为例,假设有两个特征向量:X1:房子大小(1-2000 feets), X2:卧室数量(1-5) 关于这两个特征向量的代价函数如下图所示: 从上图可以看出,代价函数是一个又瘦又高的椭圆形轮廓 ...
- poj 3276(反转)
传送门:Problem 3276 参考资料: [1]:挑战程序设计竞赛 先献上AC代码,题解晚上再补 题意: John有N头牛,这些牛有的头朝前("F"),有的朝后("B ...
- 中南大学2018年ACM暑期集训前期训练题集(入门题) Q: Simple Line Editor
数据有毒,一个一个读字符是错,整个字符串读入,一次就A了. 总之,数据总是没有错的,还是对c++了解地不够深刻,还有,在比赛中,一定要有勇气重构代码 错误代码: #include<iostrea ...