【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* ...
随机推荐
- OneProxy构建
OneProxy的主要功能有:1. 垂直分库 2. 水平分表 3. Proxy集群 4. 读高可用 5. 读写分离(master不参与读) 6. 读写分离(master参与读) 7. 写高可用 8. ...
- luogu1345 奶牛的电信 (最小割)
虽然割点不好搞,但是可以变成割边呀 拆点,拆出来的边权给1,原图中的边权给inf,然后跑dinic就行了 #include<bits/stdc++.h> #define pa pair&l ...
- 【ATcoder s8pc_3 F】 寿司
http://s8pc-3.contest.atcoder.jp/tasks/s8pc_3_f (题目链接) 题意 有一个长度为$N$的数列$A$,初始为$0$.$Q$次操作,每次两个参数$x,y$. ...
- 爬楼梯问题 leetcode70
假设你正在爬楼梯,需要n阶你才能到达楼顶,n是正整数 每次你可以爬1或2个台阶,有多少种不同的方法可以爬到楼顶 当n=1时,steps=1 当n=2时,1+1,2 steps=2 当n=3时,1+1+ ...
- 【UVA10140】Prime Distance
题目大意:求出一个给定区间 [l, r] 内相邻素数之间的最大距离和最小距离. 题解:由于 l, r 的范围太大,没法直接用筛法得出区间的素数.考虑筛出区间的素数等价于筛掉区间内的所有和数, 根据算术 ...
- 走进JVM【二】理解JVM内存区域
引言 对于C++程序员,内存分配与回收的处理一直是令人头疼的问题.Java由于自身的自动内存管理机制,使得管理内存变得非常轻松,不容易出现内存泄漏,溢出的问题. 不容易不代表不会出现问题,一旦内存泄漏 ...
- NO.11 复制时勿忘其每个成分
1.Coping 函数应该确保复制对象内的"每一个成员变量",和调用合适的 "base class"构造函数(base class 某些成员往往是private ...
- mui dtpicker 时间的设置 以及MUI的弹窗
1)引入mui.min.css,然后引入mui.picker.min.css 注意这个mui.picker.min.css 与 mui.picker.css 不一样 2)引入 ...
- CentOS6.7下Ansible部署
Ansible是一种集成IT系统的配置管理, 应用部署, 执行特定任务的开源平台. 它基于Python语言实现, 部署只需在主控端部署Ansible环境, 被控端无需安装代理工具, 只需打开SSH, ...
- 计算机网络原理和OSI模型与TCP模型
计算机网络原理和OSI模型与TCP模型 一.计算机网络的概述 1.计算机网络的定义 计算机网络是一组自治计算机的互连的集合 2.计算机网络的基本功能 a.资源共享 b.分布式处理与负载均衡 c.综合信 ...