BZOJ1901 ZOJ2112 线段树+treap (线段树套线段树)
BZOJ1901:
线段树套线段树做法:
(外层线段树 里层动态开节点的权值线段树)
有一个小小的trick 可以省掉二分变成nlog^2n的
就是把查询的区间都取出来… logn个一起走…
2016.2.14Upd
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=10050;
int root[N*8],n,m,cnt,tot,base[N*2],L[N*200],R[N*200],tree[N*200],a[N],stk[N],top;
struct Ask{char s[3];int i,j,k;}ask[N];
void Insert(int l,int r,int &pos,int wei,int f){
if(!pos)pos=++cnt;tree[pos]+=f;
if(l==r)return;
int mid=(l+r)>>1;
if(mid<wei)Insert(mid+1,r,R[pos],wei,f);
else Insert(l,mid,L[pos],wei,f);
}
void insert(int l,int r,int pos,int num,int wei,int f){
Insert(1,tot,root[pos],wei,f);
if(l==r)return;
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<num)insert(mid+1,r,rson,num,wei,f);
else insert(l,mid,lson,num,wei,f);
}
void query(int l,int r,int pos,int L,int R){
if(l>=L&&r<=R){stk[++top]=root[pos];return;}
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)query(mid+1,r,rson,L,R);
else if(mid>=R)query(l,mid,lson,L,R);
else query(l,mid,lson,L,R),query(mid+1,r,rson,L,R);
}
int Query(int xx,int yy,int kth){
top=0,query(1,n,1,xx,yy);
int l=1,r=tot;
while(l<r){
int temp=0;
for(int i=1;i<=top;i++)temp+=tree[L[stk[i]]];
if(temp>=kth){
r=(l+r)>>1;
for(int i=1;i<=top;i++)stk[i]=L[stk[i]];
}
else{
l=(l+r)/2+1,kth-=temp;
for(int i=1;i<=top;i++)stk[i]=R[stk[i]];
}
}
printf("%d\n",base[l]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),base[++tot]=a[i];
for(int i=1;i<=m;i++){
scanf("%s%d%d",ask[i].s,&ask[i].i,&ask[i].j);
if(ask[i].s[0]=='Q')scanf("%d",&ask[i].k);
else base[++tot]=ask[i].j;
}
sort(base+1,base+1+tot);tot=unique(base+1,base+1+tot)-base-1;
for(int i=1;i<=n;i++)insert(1,n,1,i,lower_bound(base+1,base+1+tot,a[i])-base,1);
for(int i=1;i<=m;i++){
if(ask[i].s[0]=='Q')Query(ask[i].i,ask[i].j,ask[i].k);
else{
insert(1,n,1,ask[i].i,lower_bound(base+1,base+1+tot,a[ask[i].i])-base,-1);
insert(1,n,1,ask[i].i,lower_bound(base+1,base+1+tot,ask[i].j)-base,1);
a[ask[i].i]=ask[i].j;
}
}
}
线段树+treap
//By SiriusRen
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 600050
char op[3];
int n,m,t,root[N],size,a[N],tmp,L,R,xx;
struct Treap{int ch[2],v,cnt,rnd,sz;}tr[N];
void Upd(int k){tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz+tr[k].cnt;}
void rot(int &k,bool f){int t=tr[k].ch[f];tr[k].ch[f]=tr[t].ch[!f],tr[t].ch[!f]=k,Upd(k),Upd(t),k=t;}
void insert(int &k,int num){
if(!k){k=++size;tr[k].cnt=tr[k].sz=1,tr[k].rnd=rand(),tr[k].v=num;return;}
tr[k].sz++;
if(tr[k].v==num){tr[k].cnt++;return;}
bool f=num>tr[k].v;
insert(tr[k].ch[f],num);
if(tr[tr[k].ch[f]].rnd<tr[k].rnd)rot(k,f);
}
void Build(int l,int r,int pos){
insert(root[pos],a[t]);
if(l==r)return;
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid>=t)Build(l,mid,lson);
else Build(mid+1,r,rson);
}
void query(int k,int num){
if(!k)return;
if(tr[k].v==num){tmp+=tr[tr[k].ch[0]].sz;return;}
else if(tr[k].v>num)query(tr[k].ch[0],num);
else tmp+=tr[tr[k].ch[0]].sz+tr[k].cnt,query(tr[k].ch[1],num);
}
void Query(int l,int r,int pos,int num){
if(l>=L&&r<=R){query(root[pos],num);return;}
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)Query(mid+1,r,rson,num);
else if(mid>=R)Query(l,mid,lson,num);
else Query(l,mid,lson,num),Query(mid+1,r,rson,num);
}
void b_srch(){
int l=0,r=0x3fffffff,Ans=0;
while(l<=r){
int mid=(l+r)>>1;
tmp=1,Query(1,n,1,mid);
if(tmp<=xx)Ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",Ans);
}
void del(int &k,int num){
if(tr[k].v==num){
if(tr[k].cnt>1)tr[k].sz--,tr[k].cnt--;
else if(tr[k].ch[0]*tr[k].ch[1]==0)k=tr[k].ch[0]+tr[k].ch[1];
else rot(k,tr[tr[k].ch[0]].rnd>tr[tr[k].ch[1]].rnd),del(k,num);
}
else tr[k].sz--,del(tr[k].ch[num>tr[k].v],num);
}
void Change(int l,int r,int pos){
del(root[pos],a[L]),insert(root[pos],xx);
if(l==r)return;
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)Change(mid+1,r,rson);
else Change(l,mid,lson);
}
int main(){
scanf("%d%d",&n,&m);
for(t=1;t<=n;t++)
scanf("%d",&a[t]),Build(1,n,1);
for(int i=1;i<=m;i++){
scanf("%s",op);
if(op[0]=='Q')scanf("%d%d%d",&L,&R,&xx),b_srch();
else scanf("%d%d",&L,&xx),Change(1,n,1),a[L]=xx;
}
}
加个多case就是ZOJ2112了:
//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1000050
char op[3];
int n,m,t,root[50050*8],size,a[50050],tmp,L,R,xx,cases;
struct Treap{int ch[2],v,cnt,rnd,sz;}tr[N];
void Upd(int k){tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz+tr[k].cnt;}
void rot(int &k,bool f){int t=tr[k].ch[f];tr[k].ch[f]=tr[t].ch[!f],tr[t].ch[!f]=k,Upd(k),Upd(t),k=t;}
void insert(int &k,int num){
if(!k){k=++size;tr[k].cnt=tr[k].sz=1,tr[k].rnd=rand(),tr[k].v=num;return;}
tr[k].sz++;
if(tr[k].v==num){tr[k].cnt++;return;}
bool f=num>tr[k].v;
insert(tr[k].ch[f],num);
if(tr[tr[k].ch[f]].rnd<tr[k].rnd)rot(k,f);
}
void Build(int l,int r,int pos){
insert(root[pos],a[t]);
if(l==r)return;
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid>=t)Build(l,mid,lson);
else Build(mid+1,r,rson);
}
void query(int k,int num){
if(!k)return;
if(tr[k].v==num){tmp+=tr[tr[k].ch[0]].sz;return;}
else if(tr[k].v>num)query(tr[k].ch[0],num);
else tmp+=tr[tr[k].ch[0]].sz+tr[k].cnt,query(tr[k].ch[1],num);
}
void Query(int l,int r,int pos,int num){
if(l>=L&&r<=R){query(root[pos],num);return;}
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)Query(mid+1,r,rson,num);
else if(mid>=R)Query(l,mid,lson,num);
else Query(l,mid,lson,num),Query(mid+1,r,rson,num);
}
void b_srch(){
int l=0,r=0x3fffffff,Ans=0;
while(l<=r){
int mid=(l+r)>>1;
tmp=1,Query(1,n,1,mid);
if(tmp<=xx)Ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",Ans);
}
void del(int &k,int num){
if(tr[k].v==num){
if(tr[k].cnt>1)tr[k].sz--,tr[k].cnt--;
else if(tr[k].ch[0]*tr[k].ch[1]==0)k=tr[k].ch[0]+tr[k].ch[1];
else rot(k,tr[tr[k].ch[0]].rnd>tr[tr[k].ch[1]].rnd),del(k,num);
}
else tr[k].sz--,del(tr[k].ch[num>tr[k].v],num);
}
void Change(int l,int r,int pos){
del(root[pos],a[L]),insert(root[pos],xx);
if(l==r)return;
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)Change(mid+1,r,rson);
else Change(l,mid,lson);
}
int main(){
scanf("%d",&cases);
while(cases--){
size=0,memset(root,0,sizeof(root));
scanf("%d%d",&n,&m);
for(int i=0;i<=n*20;i++)tr[i].ch[0]=tr[i].ch[1]=tr[i].v=tr[i].sz=tr[i].cnt=0;
for(t=1;t<=n;t++)
scanf("%d",&a[t]),Build(1,n,1);
for(int i=1;i<=m;i++){
scanf("%s",op);
if(op[0]=='Q')scanf("%d%d%d",&L,&R,&xx),b_srch();
else scanf("%d%d",&L,&xx),Change(1,n,1),a[L]=xx;
}
}
}
BZOJ1901 ZOJ2112 线段树+treap (线段树套线段树)的更多相关文章
- 【学习笔记】浅析平衡树套线段树 & 带插入区间K小值
常见的树套树 一般来说,在嵌套数据结构中,线段树多被作为外层结构使用. 但线段树毕竟是 静态 的结构,导致了一些不便. 下面是一个难以维护的例子: 带插入区间 \(k\) 小值问题 来源:Luogu ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1807 Solved: 772[Submit][Stat ...
- BZOJ_1901_&_ZJU_2112_Dynamic_Rankings_(主席树+树状数组/线段树+(Treap/Splay))
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1901 给出一个长度为n的数列A,有m次询问,询问分两种:1.修改某一位置的值;2.求区间[l, ...
- bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629[Submit][Stat ...
- [BZOJ 3196] 213平衡树 【线段树套set + 树状数组套线段树】
题目链接:BZOJ - 3196 题目分析 区间Kth和区间Rank用树状数组套线段树实现,区间前驱后继用线段树套set实现. 为了节省空间,需要离线,先离散化,这样需要的数组大小可以小一些,可以卡过 ...
- [BZOJ 1901] Dynamic Rankings 【树状数组套线段树 || 线段树套线段树】
题目链接:BZOJ - 1901 题目分析 树状数组套线段树或线段树套线段树都可以解决这道题. 第一层是区间,第二层是权值. 空间复杂度和时间复杂度均为 O(n log^2 n). 线段树比树状数组麻 ...
- ZOJ-2112-Dynamic Rankings(线段树套splay树)
题意: 完成两个操作: 1.询问一个区间里第k小的数: 2.修改数列中一个数的值. 分析: 线段树套平衡树,线段树中的每个节点都有一棵平衡树,维护线段树所记录的这个区间的元素.这样处理空间上是O(nl ...
- ZJOI 2017 树状数组(线段树套线段树)
题意 http://uoj.ac/problem/291 思路 不难发现,九条カレン醬所写的树状数组,在查询区间 \([1,r]\) 的时候,其实在查询后缀 \([r,n]\) :在查询 \([l,r ...
随机推荐
- 火狐添加消息头 Modify Header Value (HTTP Headers)
火狐浏览器添加组件 : Modify Header Value (HTTP Headers)
- Centos6.6 yum源更新
1备份: cp /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d//CentOS-Base.repo.ori 2下载: wget -O /etc/y ...
- unity Android在streamingAssets路径下文件无法读取的的解决方法
unity Android在streamingAssets路径下文件,有时候plugin下的.jar或者.so无法直接读取: 解决方法之一,拷贝至其他路径: #if UNITY_ANDROID str ...
- 洛谷 P2738 [USACO4.1]篱笆回路Fence Loops
P2738 [USACO4.1]篱笆回路Fence Loops 题目描述 农夫布朗的牧场上的篱笆已经失去控制了.它们分成了1~200英尺长的线段.只有在线段的端点处才能连接两个线段,有时给定的一个端点 ...
- 关于Android制作.9.png图片
第一个问题,.9格式的图片与我们之前的一般图片有什么问题呢? 这是安卓开发里面的一种特殊的图片. 这样的格式的图片在android 环境下具有自适应调节大小的能力. (1)同意开发者定义可扩展区域,当 ...
- gem5中event queue执行原理机制具体分析
搞清楚这个花了两天时间,下面内容为简略版.为了给自己赚点下载用的积分.如须要具体版本号.请点击下载点击打开链接 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQ ...
- Linux下安装Mysql(RPM安装)
一.去官网下载本次安装须要的mysql版本号.我们须要安装的是5.1版本号的且centos系统是64位的.所下面载的是MySQL-community-5.1.73-1.rhel5.x86_64.rpm ...
- 6.deque
#include <iostream> #include <deque> #include <algorithm> using namespace std; //序 ...
- SecondaryNameNode合并元信息过程
- solver及其配置
solver算是caffe的核心的核心,它协调着整个模型的运作.caffe程序运行必带的一个参数就是solver配置文件.运行代码一般为 # caffe train --solver=*_slover ...