zoukankan      html  css  js  c++  java
  • 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();
    }
    

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

  • 相关阅读:
    叙旧
    注册表的基本操作(.Net)
    如何自己实现 JavaScript 的 new 操作符?
    装饰者模式和TypeScript装饰器
    彻底弄懂GMT、UTC、时区和夏令时
    Javascript 中 cookie 操作方式
    javascript实例教程:使用canvas技术模仿echarts柱状图
    实现memcached客户端:TCP、连接池、一致性哈希、自定义协议
    Linux终端快速检测网站是否宕机的6个方法
    爬虫是什么吗?你知道爬虫的爬取流程吗?
  • 原文地址:https://www.cnblogs.com/Tobichi/p/9107763.html
Copyright © 2011-2022 走看看