zoukankan      html  css  js  c++  java
  • bzoj3196 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

    HINT

    1.n和m的数据范围:n,m<=50000


    2.序列中每个数的数据范围:[0,1e8]


    3.虽然原题没有,但事实上5操作的k可能为负数
     

    树套树第一题……写了好久啊……

    其实是不难的……但是变量真的好多……

    用线段树维护区间,对于每个区间都把区间内所有的数扔进一棵平衡树中,查询的时候对于线段树的每一个区间都在平衡树上找

    这样是nlog^2n的

    找区间第k大的时候还要二分,所以其实极限数据是nlog^3n的

    在bzoj上9.8s跑过……这时限卡的我也是醉了

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<deque>
    #include<set>
    #include<map>
    #include<ctime>
    #define LL long long
    #define inf 0x7ffffff
    #define pa pair<int,int>
    #define pi 3.1415926535897932384626433832795028841971
    #define N 200010
    #define M 3000010
    using namespace std;
    inline LL read()
    {
        LL x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,m,treesize,wrk;
    int l[M],r[M],rnd[M],dat[M],son[M],rep[M];
    int root[N],a[N];
    inline void update(int k){son[k]=son[l[k]]+son[r[k]]+rep[k];}
    inline void right_rotate(int &k){int t=l[k];l[k]=r[t];r[t]=k;son[t]=son[k];update(k);k=t;}
    inline void left_rotate(int &k){int t=r[k];r[k]=l[t];l[t]=k;son[t]=son[k];update(k);k=t;}
    inline void insert(int &k,int x)
    {
    	if (!k){k=++treesize;dat[k]=x;rnd[k]=rand();rep[k]=son[k]=1;return;}
    	son[k]++;
    	if (x==dat[k]){rep[k]++;return;}
    	else if (x<dat[k])
    	{	
    		insert(l[k],x);
    		if (rnd[l[k]]>rnd[k])right_rotate(k);
    	}
    	else if (x>dat[k])
    	{
    		insert(r[k],x);
    		if (rnd[r[k]]>rnd[k])left_rotate(k);
    	}
    }
    inline void del(int &k,int x)
    {
    	if (!k)return;
        if(dat[k]==x)
        {
            if(rep[k]>1){rep[k]--;son[k]--;return;}
            if(l[k]*r[k]==0)k=l[k]+r[k];
            else if(rnd[l[k]]>rnd[r[k]]){right_rotate(k);del(k,x);}
            else {left_rotate(k);del(k,x);}
        }else if(x<dat[k]){del(l[k],x);son[k]--;}
        else {del(r[k],x);son[k]--;}
    }
    inline void buildtree(int k,int l,int r,int x,int dat)
    {
    	insert(root[k],dat);
    	if (l==r)return;
    	int mid=(l+r)>>1;
    	if (x<=mid)buildtree(k<<1,l,mid,x,dat);
    	else buildtree(k<<1|1,mid+1,r,x,dat);
    }
    inline void get_rank(int k,int x)
    {
    	if (!k)return;
    	if (x==dat[k]){	wrk+=son[l[k]];	return;	}
    	if (x<dat[k])get_rank(l[k],x);
    	if (x>dat[k])
    	{
    		wrk+=son[l[k]]+rep[k];
    		get_rank(r[k],x);
    	}
    }
    inline void ask_rank(int k,int l,int r,int x,int y,int dat)
    {
    	if (l==x&&r==y){get_rank(root[k],dat);return;}
    	int mid=(l+r)>>1;
    	if (y<=mid)ask_rank(k<<1,l,mid,x,y,dat);
    	else if (x>mid)ask_rank(k<<1|1,mid+1,r,x,y,dat);
    	else
    	{
    		ask_rank(k<<1,l,mid,x,mid,dat);
    		ask_rank(k<<1|1,mid+1,r,mid+1,y,dat);
    	}
    }
    inline int ask_kth(int x,int y,int dat)
    {
    	int l=0,r=inf,ans=0;
    	while (l<=r)
    	{
    		int mid=(l+r)>>1;
    		wrk=1;ask_rank(1,1,n,x,y,mid);
    		if (wrk<=dat){l=mid+1;ans=mid;}
    		else r=mid-1;
    	}
    	return ans;
    }
    inline void change(int k,int l,int r,int x,int dat,int todel)
    {
    	del(root[k],todel);
    	insert(root[k],dat);
    	if (l==r)return;
    	int mid=(l+r)>>1;
    	if (x<=mid)change(k<<1,l,mid,x,dat,todel);
    	else change(k<<1|1,mid+1,r,x,dat,todel);
    }
    inline void get_pred(int k,int x)
    {
    	if (!k)return;
    	if (x>dat[k])
    	{
    		wrk=max(wrk,dat[k]);
    		get_pred(r[k],x);
    	}else get_pred(l[k],x);
    }
    inline void pred(int k,int l,int r,int x,int y,int dat)
    {
    	if (l==x&&r==y){get_pred(root[k],dat);return;}
    	int mid=(l+r)>>1;
    	if (y<=mid)pred(k<<1,l,mid,x,y,dat);
    	else if (x>mid)pred(k<<1|1,mid+1,r,x,y,dat);
    	else{pred(k<<1,l,mid,x,mid,dat);pred(k<<1|1,mid+1,r,mid+1,y,dat);}
    }
    inline void get_succ(int k,int x)
    {
    	if(!k)return;
    	if (x<dat[k])
    	{
    		wrk=min(wrk,dat[k]);
    		get_succ(l[k],x);
    	}else get_succ(r[k],x);
    }
    inline void succ(int k,int l,int r,int x,int y,int dat)
    {
    	if (l==x&&r==y){get_succ(root[k],dat);return;}
    	int mid=(l+r)>>1;
    	if (y<=mid)succ(k<<1,l,mid,x,y,dat);
    	else if (x>mid)succ(k<<1|1,mid+1,r,x,y,dat);
    	else{succ(k<<1,l,mid,x,mid,dat);succ(k<<1|1,mid+1,r,mid+1,y,dat);}
    }
    int main()
    {
    	n=read();m=read();
    	for (int i=1;i<=n;i++)a[i]=read();
    	for (int i=1;i<=n;i++)buildtree(1,1,n,i,a[i]);
    	for (int i=1;i<=m;i++)
    	{
    		int opr=read();
    		if (opr==1)
    		{
    			int x=read(),y=read(),z=read();
    			wrk=1;ask_rank(1,1,n,x,y,z);printf("%d
    ",wrk);
    		}else if (opr==2)
    		{
    			int x=read(),y=read(),z=read();
    			printf("%d
    ",ask_kth(x,y,z));
    		}else if (opr==3)
    		{
    			int x=read(),y=read();
    			change(1,1,n,x,y,a[x]);a[x]=y;
    		}else if (opr==4)
    		{
    			int x=read(),y=read(),z=read();
    			wrk=0;pred(1,1,n,x,y,z);printf("%d
    ",wrk);
    		}else if (opr==5)
    		{
    			int x=read(),y=read(),z=read();
    			wrk=inf;succ(1,1,n,x,y,z);printf("%d
    ",wrk);
    		}
    	}
    	return 0;
    }
    
    ——by zhber,转载请注明来源
  • 相关阅读:
    Service Name Port Number Transport Protocol tcp udp 端口号16bit
    linux linux 互传文件 win 不通过 ftp sftp 往linux 传文件(文件夹)
    soft deletion Google SRE 保障数据完整性的手段
    Taylor series
    Taylor's theorem
    Moving average
    REQUEST
    Unix file types
    mysqld.sock
    Tunneling protocol
  • 原文地址:https://www.cnblogs.com/zhber/p/4157195.html
Copyright © 2011-2022 走看看