[TYVJ 1730]二逼平衡树 线段树套平衡树

来一发树套树。1A也是很感动QAQ

就是时间复杂度略大。而且好像还有其他打法。

谨以此纪念此类型树套树入门

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define N 51000
#define size(x) ((x)?(x->size):(0))
#define lc(x) (x->ch[0])
#define rc(x) (x->ch[1])
int n,m;
struct Treap{
	Treap *ch[2];
	int v,key,size;
	Treap(int x=0){
		ch[0]=ch[1]=NULL;key=rand();size=1;v=x;
	}
}*root[N*4];
void pushup(Treap *rt){
	rt->size=size(lc(rt))+size(rc(rt))+1;
}
void turn(Treap *&rt,int d){
	Treap *t=rt->ch[d^1];
	rt->ch[d^1]=t->ch[d];
	pushup(rt);
	t->ch[d]=rt;
	pushup(t);
	rt=t;
}
void insert(Treap *&rt,int x){
	if(!rt){
		rt=new Treap(x);return;
	}
	int d=x < rt->v;
	insert(rt->ch[d^1],x);
	pushup(rt);
	if(rt->key > rt->ch[d^1]->key) turn(rt,d);
}
void del(Treap *&rt,int x){
	if(rt->v == x){
		if(lc(rt)&&rc(rt)){
			int d=lc(rt)->key < rc(rt)->key;
			turn(rt,d);
			del(rt->ch[d],x);
		}
		else{
			Treap *t=NULL;
			if(lc(rt)) t=lc(rt);
			else t=rc(rt);
			delete rt;rt=t;
		}
	}
	else{
		int d=rt->v < x;
		del(rt->ch[d],x);
	}
	if(rt) pushup(rt);
}
int pai(Treap *&rt,int x){
	if(!rt) return 0;
	if(x<= rt->v){
		return pai(lc(rt),x);
	}
	else return size(lc(rt))+1+pai(rc(rt),x);
}
int a[N];
void Insert(int l,int r,int rt){
	pos(i,l,r) insert(root[rt],a[i]);
}
void build(int l,int r,int rt){
	Insert(l,r,rt);
	if(l==r) return;
	int mid=(l+r)>>1;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
}
void update(int l,int r,int pos,int x,int y,int rt){
	del(root[rt],x);insert(root[rt],y);
	if(l==r) return;
	int mid=(l+r)>>1;
	if(pos<=mid) update(l,mid,pos,x,y,rt<<1);
	else update(mid+1,r,pos,x,y,rt<<1|1);
}
int Pai(int xl,int xr,int k,int l,int r,int rt){
	if(l>=xl&&r<=xr) return pai(root[rt],k);
	int mid=(l+r)>>1;
	int ans(0);
	if(xl<=mid) ans+=Pai(xl,xr,k,l,mid,rt<<1);
	if(xr>mid) ans+=Pai(xl,xr,k,mid+1,r,rt<<1|1);
	return ans;
}
int kth(int L,int R,int k){
	int l=0,r=(int)1e8;
	while(l<=r){
		int mid=(l+r)>>1;
		if(Pai(L,R,mid,1,n,1)+1<=k) l=mid+1;
		else r=mid-1;
	}
	return r;
}
int main(){
	scanf("%d%d",&n,&m);
	pos(i,1,n) scanf("%d",&a[i]);
	build(1,n,1);
	pos(i,1,m){
		int opt;scanf("%d",&opt);
		int l,r,k;
		if(opt==3){
			scanf("%d%d",&l,&k);
			update(1,n,l,a[l],k,1);
			a[l]=k;
			continue;
		}
		scanf("%d%d%d",&l,&r,&k);
		if(opt==1) printf("%d\n",Pai(l,r,k,1,n,1)+1);
		else if(opt==2) printf("%d\n",kth(l,r,k));
		else if(opt==4) printf("%d\n",kth(l,r,Pai(l,r,k,1,n,1)));
		else if(opt==5) printf("%d\n",kth(l,r,Pai(l,r,k+1,1,n,1)+1));
	}
	return 0;
}

  

时间: 2024-08-29 16:46:04

[TYVJ 1730]二逼平衡树 线段树套平衡树的相关文章

bzoj3196 二逼平衡树 线段树套平衡树

题意:您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继(后继定义为大于x,且最小的数) 题解:树套树,外层是一棵线段树,每个节点下有一棵平衡树(平衡树记录ls,rs,因此记录根节点就可以遍历整棵树),先不考虑空间问题,ask(l,r)可以分成多个线段树区间,每个区间下有平衡树可以查询排名,1&3-5操

bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,

BZOJ 3196: Tyvj 1730 二逼平衡树( 树套树 )

这道题做法应该很多吧.... 我用了线段树套treap.... -------------------------------------------------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> #include<cstdlib> #include<ios

bzoj 3196 &amp;&amp; luogu 3380 JoyOI 1730 二逼平衡树 (线段树套Treap)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196 题面; 3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6372  Solved: 2406[Submit][Status][Discuss] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为

BZOJ3196 二逼平衡树 【线段树套平衡树】

题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继(后继定义为大于x,且最小的数) 输入格式 第一行两个数 n,m 表示长度为n的有序序列和m个操作 第二行有n个数,表示有序序列 下面有m行,opt表示操作标号 若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名 若

【BZOJ 3196】Tyvj 1730 二逼平衡树

3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 842  Solved: 350 [Submit][Status] Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱定义为小于x,且最大的数) 5.查询k在区间内的后继(后继定义为大于x,

[Tyvj 1730] 二逼平衡树

先来一发题面QwQ [TYVJ1730]二逼平衡树 Time Limit:2 s   Memory Limit:512 MB Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行有n个数

Bzoj3196 Tyvj 1730 二逼平衡树

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3350  Solved: 1324 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查询k在区间内的后继(后继定义为大于x,且最小的数) Input 第一行两个数 n,m 表示长度为n的有序序列和m个操作第二行

树套树-线段树套平衡树

树套树留坑 线段树套平衡树: 二逼平衡树 #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> #include<map> #include<bitset> #pragma GCC optimize(2) #define rep(i,a,b) for(i