zoukankan      html  css  js  c++  java
  • 【bzoj3196】 Tyvj1730—二逼平衡树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3196 (题目链接)

    题意

      1.查询k在区间内的排名;2.查询区间内排名为k的值;3.修改某一位值上的数值;4.查询k在区间内的前驱(前驱定义为小于x,且最大的数);5.查询k在区间内的后继(后继定义为大于x,且最小的数)

    Solution

      修改不好搞,主席树套树状数组空间炸,最好的选择→_→:线段树套treap。

      对于操作2,我们二分找到一个排名大于$k$的最小的数,然后查询这个数的前驱即可。

    细节

      查询前驱和后继的时候要特判一下没有找到的情况。

    代码

    // bzoj3196
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf 2147483640
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    using namespace std;
    
    const int maxn=50010;
    int a[maxn],n,m;
    struct node {
    	int son[2],l,r,w,val,rnd,size,tree;
    	int& operator [] (int x) {return son[x];}
    };
    
    namespace Treap {
    	int sz;node tr[maxn*50];
    	void pushup(int x) {
    		tr[x].size=tr[tr[x][0]].size+tr[tr[x][1]].size+tr[x].w;
    	}
    	void rotate(int &x,int p) {
    		int y=tr[x][p];
    		tr[x][p]=tr[y][p^1];tr[y][p^1]=x;x=y;
    		pushup(tr[y][p^1]);pushup(y);
    	}
    	void insert(int &k,int x) {
    		if (!k) {tr[k=++sz].val=x;tr[k].rnd=rand();tr[k].size=tr[k].w=1;return;}
    		int p=x>tr[k].val;tr[k].size++;
    		if (x==tr[k].val) {tr[k].w++;return;}
    		insert(tr[k][p],x);
    		if (tr[tr[k][p]].rnd>tr[k].rnd) rotate(k,p);
    	}
    	void erase(int &k,int x) {
    		if (!k) return;
    		if (tr[k].val==x) {
    			if (tr[k].w>1) {tr[k].w--;tr[k].size--;return;}
    			if (tr[k][0]*tr[k][1]==0) k=tr[k][0]+tr[k][1];
    			else rotate(k,tr[tr[k][1]].rnd>tr[tr[k][0]].rnd),erase(k,x);
    		}
    		else tr[k].size--,erase(tr[k][x>tr[k].val],x);
    	}
    	int rank(int k,int x) {
    		if (!k) return 0;
    		if (x<=tr[k].val) return rank(tr[k][0],x);
    		else return rank(tr[k][1],x)+tr[tr[k][0]].size+tr[k].w;
    	}
    	int find(int k,int x) {
    		if (!k) return -1;
    		if (tr[tr[k][0]].size<x && x<=tr[tr[k][0]].size+tr[k].w) return tr[k].val;
    		else if (x<=tr[tr[k][0]].size) return find(tr[k][0],x);
    		else return find(tr[k][1],x-tr[tr[k][0]].size-tr[k].w);
    	}
    	int pref(int k,int x) {return find(k,rank(k,x));}
    	int suff(int k,int x) {return find(k,rank(k,x+1)+1);}
    }
    
    namespace Segtree {
    	node tr[maxn<<2];
    	void build(int k,int s,int t) {
    		tr[k].l=s;tr[k].r=t;
    		for (int i=s;i<=t;i++) Treap::insert(tr[k].tree,a[i]);
    		if (s==t) return;
    		int mid=(s+t)>>1;
    		build(k<<1,s,mid);build(k<<1|1,mid+1,t);
    	}
    	void modify(int k,int p,int val) {
    		int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    		Treap::erase(tr[k].tree,a[p]);
    		Treap::insert(tr[k].tree,val);
    		if (l==r) return;
    		if (p<=mid) modify(k<<1,p,val);
    		else modify(k<<1|1,p,val);
    	}
    	int rank(int k,int s,int t,int val) {
    		int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    		if (s==l && t==r) return Treap::rank(tr[k].tree,val);
    		if (t<=mid) return rank(k<<1,s,t,val);
    		else if (s>mid) return rank(k<<1|1,s,t,val);
    		else return rank(k<<1,s,mid,val)+rank(k<<1|1,mid+1,t,val);
    	}
    	int pref(int k,int s,int t,int val) {
    		int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    		if (s==l && t==r) {
    			int tmp=Treap::pref(tr[k].tree,val);
    			return tmp==-1 ? -inf : tmp;
    		}
    		if (t<=mid) return pref(k<<1,s,t,val);
    		else if (s>mid) return pref(k<<1|1,s,t,val);
    		else return max(pref(k<<1,s,mid,val),pref(k<<1|1,mid+1,t,val));
    	}
    	int suff(int k,int s,int t,int val) {
    		int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
    		if (s==l && t==r) {
    			int tmp=Treap::suff(tr[k].tree,val);
    			return tmp==-1 ? inf : tmp;
    		}
    		if (t<=mid) return suff(k<<1,s,t,val);
    		else if (s>mid) return suff(k<<1|1,s,t,val);
    		else return min(suff(k<<1,s,mid,val),suff(k<<1|1,mid+1,t,val));
    	}
    	int find(int s,int t,int k) {
    		int l=0,r=1e8,res;
    		while (l<=r) {
    			int mid=(l+r)>>1;
    			if (rank(1,s,t,mid)>=k) r=mid-1,res=mid;
    			else l=mid+1;
    		}
    		return pref(1,s,t,res);
    	}
    }
    using namespace Segtree;
    
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	build(1,1,n);
    	for (int op,x,y,k,i=1;i<=m;i++) {
    		scanf("%d%d%d",&op,&x,&y);
    		if (op==1) scanf("%d",&k),printf("%d
    ",rank(1,x,y,k)+1);
    		if (op==2) scanf("%d",&k),printf("%d
    ",find(x,y,k));
    		if (op==4) scanf("%d",&k),printf("%d
    ",pref(1,x,y,k));
    		if (op==5) scanf("%d",&k),printf("%d
    ",suff(1,x,y,k));
    		if (op==3) modify(1,x,y),a[x]=y;
    	}
    	return 0;
    }
    
  • 相关阅读:
    新一轮人工智能的兴起引发的思考
    企业应用架构的发展演进
    利用poi插件,把Excel内容读入Java,把Java中的内容输出到Exce
    mysql免安装被指
    正则表达式大全
    开发数据库步骤
    JVM
    Java面试题一
    java集合总结
    JAVA WEB回顾一
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6491389.html
Copyright © 2011-2022 走看看