P3380 【模板】二逼平衡樹(樹套樹)
排名,修改,前驅和後繼通過平衡樹都很好實現,查詢排名為k的值不是很好實現,因為這個區間可能線上段樹的多個區間內,就需要在多棵平衡樹中找,合併也不太現實,換個思路:二分值,找到排名小於k的最大值,然後在對它求一個後繼就好了。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef long long ll;
const int inf=2147483647;
const int N=50010;
int n,m,a[N];
struct Treap
{
#define ls tr[rt].l
#define rs tr[rt].r
struct node
{
int l,r,sz,val,key;
}tr[N<<5];
int cnt=0;
int newnode(int val)
{
tr[++cnt].val=val;
tr[cnt].key=rand();
tr[cnt].sz=1;
return cnt;
}
void pushup(int rt){ tr[rt].sz=tr[ls].sz+tr[rs].sz+1; }
void split(int rt,int val,int &x,int &y)
{
if(!rt)
{
x=y=0;
return ;
}
if(tr[rt].val<=val)
{
x=rt;
split(tr[rt].r,val,tr[x].r,y);
pushup(x);
return ;
}
y=rt;
split(tr[rt].l,val,x,tr[rt].l);
pushup(y);
}
int merge(int x,int y)
{
if(!x||!y) return x+y;
if(tr[x].key<=tr[y].key)
{
tr[x].r=merge(tr[x].r,y);
pushup(x);
return x;
}
tr[y].l=merge(x,tr[y].l);
pushup(y);
return y;
}
int x,y,z;
void insert(int &rt,int val)
{
split(rt,val,x,y);
rt=merge(merge(x,newnode(val)),y);
}
void del(int &rt,int val)
{
split(rt,val,x,z);
split(x,val-1,x,y);
rt=merge(merge(x,merge(tr[y].l,tr[y].r)),z);
}
int getrank(int &rt,int val)
{
split(rt,val-1,x,y);
int rank=tr[x].sz;
rt=merge(x,y);
return rank;
}
int getpre(int &rt,int val)
{
split(rt,val-1,x,y);
if(!x)
{
rt=merge(x,y);
return -inf;
}
int pre=x;
while(tr[pre].r)
{
pre=tr[pre].r;
}
rt=merge(x,y);
return tr[pre].val;
}
int getnxt(int &rt,int val)
{
split(rt,val,x,y);
if(!y)
{
rt=merge(x,y);
return inf;
}
int nxt=y;
while(tr[nxt].l)
{
nxt=tr[nxt].l;
}
rt=merge(x,y);
return tr[nxt].val;
}
}treap;
struct seg
{
struct Node
{
int l,r;
int root;
}tr[N<<2];
#define ls rt<<1
#define rs rt<<1|1
void build(int rt,int l,int r)
{
for(int i=l;i<=r;++i)
{
treap.insert(tr[rt].root,a[i]);
}
tr[rt].l=l;tr[rt].r=r;
if(l==r) return ;
int mid=l+r>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
}
int getrank(int rt,int l,int r,int k)
{
if(tr[rt].l>=l&&tr[rt].r<=r) return treap.getrank(tr[rt].root,k);
int mid=tr[rt].l+tr[rt].r>>1;
int rank=0;
if(l<=mid) rank+=getrank(ls,l,r,k);
if(r>mid) rank+=getrank(rs,l,r,k);
return rank;
}
int getnxt(int rt,int l,int r,int val)
{
if(tr[rt].l>=l&&tr[rt].r<=r) return treap.getnxt(tr[rt].root,val);
int nxt=inf;
int mid=tr[rt].l+tr[rt].r>>1;
if(l<=mid) nxt=min(nxt,getnxt(ls,l,r,val));
if(r>mid) nxt=min(nxt,getnxt(rs,l,r,val));
return nxt;
}
int getpre(int rt,int l,int r,int val)
{
if(tr[rt].l>=l&&tr[rt].r<=r) return treap.getpre(tr[rt].root,val);
int pre=-inf;
int mid=tr[rt].l+tr[rt].r>>1;
if(l<=mid) pre=max(pre,getpre(ls,l,r,val));
if(r>mid) pre=max(pre,getpre(rs,l,r,val));
return pre;
}
int getnum(int x,int y,int k)
{
int l=0,r=1e8;
while(l<r)
{
int mid=l+r>>1;
if(getrank(1,x,y,mid)<k) l=mid+1;
else r=mid;
}
return getpre(1,x,y,l);
}
void modify(int rt,int x,int val)
{
treap.del(tr[rt].root,a[x]);
treap.insert(tr[rt].root,val);
if(tr[rt].l==tr[rt].r) return ;
int mid=tr[rt].l+tr[rt].r>>1;
if(x<=mid) modify(ls,x,val);
else modify(rs,x,val);
}
}tree;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) scanf("%d",a+i);
tree.build(1,1,n);
while(m--)
{
int op,l,r,k;
scanf("%d",&op);
if(op==3)
{
scanf("%d%d",&l,&r);
tree.modify(1,l,r);
a[l]=r;
}
else
{
scanf("%d%d%d",&l,&r,&k);
if(op==1) printf("%d\n",tree.getrank(1,l,r,k)+1);
else if(op==2) printf("%d\n",tree.getnum(l,r,k));
else if(op==5) printf("%d\n",tree.getnxt(1,l,r,k));
else printf("%d\n",tree.getpre(1,l,r,k));
}
}
return 0;
}
相關文章
- BZOJ 3196 Tyvj 1730 二逼平衡樹:線段樹套splay
- 平衡二叉樹,B樹,B+樹二叉樹
- 樹套樹
- 排序二叉樹和平衡二叉樹排序二叉樹
- 平衡二叉樹二叉樹
- 平衡樹和二叉樹的區別二叉樹
- 平衡二叉樹(AVL樹),原來如此!!!二叉樹
- 平衡二叉查詢樹:紅黑樹
- 十三、Mysql之平衡二叉樹(AVL樹)MySql二叉樹
- 平衡二叉樹(AVL樹)和 二叉排序樹轉化為平衡二叉樹 及C語言實現二叉樹排序C語言
- 手擼二叉樹——AVL平衡二叉樹二叉樹
- 平衡樹
- Java實現紅黑樹(平衡二叉樹)Java二叉樹
- 平衡二叉樹(AVL)二叉樹
- 滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹(二叉查詢樹)和最優二叉樹二叉樹
- P3391 【模板】文藝平衡樹
- P3369 【模板】普通平衡樹(treap)
- 資料結構之樹結構概述(含滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹、紅黑樹、B-樹、B+樹、B*樹)資料結構二叉樹
- Java 樹結構實際應用 四(平衡二叉樹/AVL樹)Java二叉樹
- 自動平衡二叉樹的構建-AVL樹二叉樹
- 110. 平衡二叉樹二叉樹
- P3369 【模板】普通平衡樹 —— Treap FHQtreapQT
- P3391 【模板】文藝平衡樹(Splay)
- 二叉樹的深度、寬度遍歷及平衡樹二叉樹
- Python 樹表查詢_千樹萬樹梨花開,忽如一夜春風來(二叉排序樹、平衡二叉樹)Python排序二叉樹
- 程式碼隨想錄——二叉樹-12.平衡二叉樹二叉樹
- 如何判斷一棵樹是否是二叉平衡樹~
- 二叉堆、BST 與平衡樹
- LeetCode-110-平衡二叉樹LeetCode二叉樹
- JZ-039-平衡二叉樹二叉樹
- 文藝平衡樹
- 平衡查詢樹
- FHQ-Treap P3369 【模板】普通平衡樹
- 樹套樹從入門到去世
- python實現非平衡二叉樹Python二叉樹
- 每日一練(28):平衡二叉樹二叉樹
- 資料結構-平衡二叉樹資料結構二叉樹
- 二叉平衡樹 python 列表 遞迴Python遞迴