Bzoj 3196 Tyvj 1730 二逼平衡树

3196: Tyvj 1730 二逼平衡树

>原题链接<

Description

您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
1.查询k在区间内的排名
2.查询区间内排名为k的值
3.修改某一位值上的数值
4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)
5.查询k在区间内的后继(后继定义为大于x,且最小的数)

Input

第一行两个数 n,m 表示长度为n的有序序列和m个操作
第二行有n个数,表示有序序列
下面有m行,opt表示操作标号
若opt=1 则为操作1,之后有三个数l,r,k 表示查询k在区间[l,r]的排名
若opt=2 则为操作2,之后有三个数l,r,k 表示查询区间[l,r]内排名为k的数
若opt=3 则为操作3,之后有两个数pos,k 表示将pos位置的数修改为k
若opt=4 则为操作4,之后有三个数l,r,k 表示查询区间[l,r]内k的前驱
若opt=5 则为操作5,之后有三个数l,r,k 表示查询区间[l,r]内k的后继

Output

对于操作1,2,4,5各输出一行,表示查询结果

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

思路:

  这种题就不需要思路了吧,我几乎是写了一个最麻烦的线段树套Treap(比较经典的树套树),几位机房大佬有写不到100行的树状数组套主席树>这里<

上一下代码,留待日后温习:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cctype>
#define ls p<<1
#define rs p<<1|1
#define O2 __attribute__((optimize("-O2")))
using namespace std;
const int inf = 2147483647;
const int N = 51000;
const int M = 2000010;
int n, m;
int a[N];
class ReadIn {
	private:
	O2 inline char nc() {
		static char buf[100000], *p1, *p2;
		return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
	}
	public:
	O2 inline int Read() {
		int x=0,f=1;char ch=nc();
		while(!isdigit(ch)){if(ch=='-')f=-1;ch=nc();};
		while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=nc();}
		return x*f;
	}
	O2 inline char getc() {
		char ch=nc();
		while(isspace(ch))ch=nc();
		return ch;
	}
}Rd;
class Treap {
	int cnt;
	struct Tree {
		int siz,key,val,v;
		int s[2];
	}Tr[M];
private:
	O2 int Build(int x) {
		cnt++;
		Tr[cnt].key = rand();
		Tr[cnt].val = x;
		Tr[cnt].siz = 1;
		Tr[cnt].v = 1;
		Tr[cnt].s[0] = Tr[cnt].s[1] = 0;
		return cnt;
	}
	O2 void Update(int x) {
		Tr[x].siz = 
		  Tr[x].v + 
		  Tr[Tr[x].s[0]].siz + 
		  Tr[Tr[x].s[1]].siz ;
	}
	O2 void Rotate(int &x,int i) {
		int p = Tr[x].s[i];
		Tr[x].s[i] = Tr[p].s[i^1];
		Tr[p].s[i^1] = x;
		Update(x);
		Update(p);
		x = p;
	}
public:
	O2 void Insert(int &p, int k) {
		if(!p) {
			p=Build(k);
		}
		else if(Tr[p].val==k) {
			Tr[p].v++;
		}
		else {
			if(Tr[p].val<k) {
				Insert(Tr[p].s[1], k);
				if(Tr[Tr[p].s[1]].key>Tr[p].key) {
					Rotate(p, 1);
				}
			}
			else {
				Insert(Tr[p].s[0], k);
				if(Tr[Tr[p].s[0]].key > Tr[p].key) {
					Rotate(p, 0);
				}
			}
		}
		Update(p);
	}
	O2 void Del(int &p, int k) {
		if(Tr[p].val < k) {
			Del(Tr[p].s[1],k);
		}
		else if(Tr[p].val > k) {
			Del(Tr[p].s[0],k);
		}
		else {
			if(Tr[p].v > 1) {
				Tr[p].v -- ;
			}
			else {
				if(Tr[p].s[0]*Tr[p].s[1] == 0) {
					p = Tr[p].s[0] + Tr[p].s[1];
				}
				else {
					if(Tr[Tr[p].s[0]].key > Tr[Tr[p].s[1]].key) {
						Rotate(p, 0);
						Del(Tr[p].s[1], k);
					}
					else {
						Rotate(p, 1);
						Del(Tr[p].s[0], k);
					}
				}
			}
		}
		if(p) {
			Update(p);
		}
	}
	O2 int Rank(int p, int k) {
		if(!p) {
			return 0;
		}
		if(Tr[p].val > k) {
			return Rank(Tr[p].s[0], k);
		}
		else if(Tr[p].val < k) {
			return Rank(Tr[p].s[1],k) + 
				   Tr[Tr[p].s[0]].siz + 
				   Tr[p].v;
		}
		else {
			return Tr[Tr[p].s[0]].siz;
		}
	}
	O2 int Pre(int p, int k) {
		if(!p) {
			return -inf;
		}
		if(Tr[p].val >= k) {
			return Pre(Tr[p].s[0], k);
		}
		else {
			return max(Tr[p].val,
					   Pre(Tr[p].s[1],k));
		}
	}
	O2 int Suc(int p, int k) {
		if(!p) {
			return inf;
		}
		if(Tr[p].val <= k) {
			return Suc(Tr[p].s[1], k);
		}
		else {
			return min(Tr[p].val,
					   Suc(Tr[p].s[0],k));
		}
	}

}Trp;
class SegmentTree {
private:
	struct Tree {
		int l, r, root;
		int minn;
	}Tr[M];
	O2 void Build(int l,int r,int p) {
		Tr[p].l = l;
		Tr[p].r = r;
		int i;
		for(i=l;i<=r;i++) {
			Trp.Insert(Tr[p].root, a[i]);
		}
		if(l==r) {
			Tr[p].minn=a[l];
			return ;
		}
		if(l!=r) {
			int mid = (l+r) >> 1;
			Build(l,mid,ls);
			Build(mid+1,r,rs);
		}
		Tr[p].minn=min(Tr[ls].minn,Tr[rs].minn);

	}
	O2 void Change(int p, int x, int c) {
		Trp.Del(Tr[p].root,a[x]);
		Trp.Insert(Tr[p].root,c);
		int &l = Tr[p].l, 
			&r = Tr[p].r;
		if(l==r) 
		{
			Tr[p].minn=c;
			return;
		}
		int mid = (l+r) >> 1;
		if(x<=mid) {
			Change(ls, x, c);
		}
		else {
			Change(rs, x, c);
		}
		Tr[p].minn=min(Tr[ls].minn,Tr[rs].minn);
	}
	O2 int Pre(int l, int r, int p, int k) {
		int &ll = Tr[p].l, 
			&rr = Tr[p].r;
		if(ll>r||rr<l) {
			return -inf;
		}
		if(ll>=l&&rr<=r) {
			return Trp.Pre(Tr[p].root,k);
		}
		else {
			return max(Pre(l, r, ls, k), 
					   Pre(l, r, rs, k));
		}
	}
	O2 int Suc(int l, int r,int p,int k) {
		int &ll = Tr[p].l, 
			&rr = Tr[p].r;
		if(ll>r||rr<l) {
			return inf;
		}
		if(ll>=l&&rr<=r) {
			return Trp.Suc(Tr[p].root,k);
		}
		else {
			return min(Suc(l, r, ls, k), 
					   Suc(l, r, rs, k));
		}
	}
	O2 int Rank(int l, int r,int p,int k) {
		int &ll = Tr[p].l, 
			&rr = Tr[p].r;
		if(ll>r||rr<l) {
			return 0;
		}
		if(ll>=l&&rr<=r) {
			return Trp.Rank(Tr[p].root,k);
		}
		else {
			return Rank(l, r, ls, k)+
				   Rank(l, r, rs, k);
		}
	}
	O2 int Sum(int l,int r,int k) {
		int ll = 0, 
			rr = (int) 1e9;
		while(ll<rr) {
			int mid = (ll + rr + 1) >> 1;
			if(Rank(l,r,1,mid)<k) {
				ll=mid;
			}
			else {
				rr=mid-1;
			}
		}
		return rr;
	}
	O2 int query(int l,int r,int p,int x,int y) {
		if(l>=x&&y>=r) {
			return Tr[p].minn;
		}
		int mid=(l+r)>>1;
		int rt=0x3f3f3f3f;
		if(x<=mid) {
			rt=min(rt,query(l,mid,ls,x,y));
		}
		if(y>mid) {
			rt=min(rt,query(mid+1,r,rs,x,y));
		}
		return rt;
	}
public:
	O2 void Solve() {
		Build(1, n, 1);
		int i,opt,l,r,k,x;
		for(i=1;i<=m;i++) {
			opt=Rd.Read();
			switch (opt) {
				case 1 : 
					l=Rd.Read(), 
					r=Rd.Read(), 
					k=Rd.Read();
					printf("%d
",Rank(l,r,1,k)+1);
					break;
				case 2 :
					l=Rd.Read(), 
					r=Rd.Read(), 
					k=Rd.Read();
					printf("%d
",Sum(l,r,k));
					break;
				case 3 :
					k=Rd.Read(), 
					x=Rd.Read();
					Change(1,k,x);
					a[k] = x;
					break;
				case 4 :
					l=Rd.Read(), 
					r=Rd.Read(), 
					k=Rd.Read();
					printf("%d
", Pre(l, r, 1, k));
					break;
				case 5 :
					l=Rd.Read(), 
					r=Rd.Read(), 
					k=Rd.Read();
					printf("%d
", Suc(l, r, 1, k));
					break;
			}
		}
	}
}Seg;
O2 int main() {
	srand(20402);
	n=Rd.Read(),
	m=Rd.Read();
	int i;
	for(i=1;i<=n;i++) 
		a[i]=Rd.Read();
	Seg.Solve();
}

 欢迎来原博客看看 >原文链接<

原文地址:https://www.cnblogs.com/Tobichi/p/9107763.html