zoukankan      html  css  js  c++  java
  • 【洛谷P2596】【ZJOI2006】—书架(FHQ_Treap)

    传送门

    考虑到每个点需要维护一个numnum和一个valval分别表示在书架内的排名和编号
    我们再记录一个to[x]to[x]表示编号xx的书的排名

    考虑以valval为优先级建TreapTreap

    对应5种操作:

    1:把ss先删去再将排名设成一个最小的数插入
    2:把ss删去后把排名设成一个最大数插入
    3:把sss+Ts+T提出来交换一下他们的numnumvalval,再交换一下toto就可以了
    4:求ss的排名
    5:求第kk大,维护一下sizesize就可以了

    都是平衡树常规操作

    调了40多分钟发现randrand写丑了,也是没谁了

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=500006;
    int siz[N],son[N][2],num[N],val[N],tot,key[N],to[N],seed,rt,n,m,mn,mx;
    #define lc(u) son[u][0]
    #define rc(u) son[u][1]
    inline int rnd(){
    	return ((rand()*1ll)<<15)%1000000000;
    }
    inline int addnode(int x,int p){
    	siz[++tot]=1,val[tot]=x,num[tot]=p,key[tot]=rnd();
    	lc(tot)=rc(tot)=0;return tot;
    }
    inline int pushup(int u){
    	siz[u]=siz[lc(u)]+siz[rc(u)]+1;
    }
    inline void split(int u,int &a,int &b,int k){
    	if(u==0){
    		a=b=0;return;
    	}
    	if(val[u]<=k){
    		a=u,split(rc(u),rc(a),b,k);
    	}
    	else {
    		b=u,split(lc(u),a,lc(b),k);
    	}
    	pushup(u);
    }
    inline void merge(int &u,int a,int b){
    	if(!a||!b){
    		u=a+b;return;
    	}
    	if(key[a]<key[b])u=a,merge(rc(u),rc(a),b);
    	else u=b,merge(lc(u),a,lc(b));
    	pushup(u);
    }
    inline int find(int x,int k){
    	while(siz[lc(x)]+1!=k){
    		if(siz[lc(x)]>=k)
    			x=lc(x);
    		else k-=siz[lc(x)]+1,x=rc(x);
    	}
    	return x;
    }
    inline void insert(int k,int p){
    	int r1=0,r2=0,u;
    	u=addnode(k,p);
    	split(rt,r1,r2,k);
    	merge(r1,r1,u);
    	merge(rt,r1,r2);
    }
    inline void delet(int x){
    	int r1=0,r2=0,r3=0;
    	split(rt,r1,r2,x);
    	split(r1,r1,r3,x-1);
    	merge(r3,lc(r3),rc(r3));
    	merge(r1,r1,r3);
    	merge(rt,r1,r2);
    }
    inline int getrk(int k){
    	int r1=0,r2=0;
    	split(rt,r1,r2,k-1);
    	int res=siz[r1]+1;
    	merge(rt,r1,r2);
    	return res;
    }
    inline int getval(int k){
    	return num[find(rt,k)];
    }
    inline int pre(int k){
    	int r1=0,r2=0;
    	split(rt,r1,r2,k-1);
    	int u=find(r1,siz[r1]);merge(rt,r1,r2);
    	return u;
    }
    inline int nxt(int k){
    	int r1=0,r2=0;
    	split(rt,r1,r2,k);
    	int u=find(r2,1);merge(rt,r1,r2);
    	return u;
    }
    char op[10];
    int main(){
    	srand(time(NULL));
    	n=read(),m=read();
    	mx=n,mn=1;
    	for(int i=1;i<=n;i++){
    		int k=read();insert(i,k),to[k]=i;
    	}
    	for(int i=1;i<=m;i++){
    		scanf("%s",op);int u=read();
    		switch(op[0]){
    			case 'T':{
    				delet(to[u]),to[u]=--mn;
    				insert(to[u],u);	
    				break;
    			}
    			case 'B':{
    				delet(to[u]),to[u]=++mx;
    				insert(to[u],u);
    				break;
    			}
    			case 'I':{
    				int k=read(),p,now;
    				if(k==0)break;
    				if(k==-1)p=pre(to[u]),now=nxt(to[num[p]]);
    				else if(k==1)p=nxt(to[u]),now=pre(to[num[p]]);
    				swap(to[num[p]],to[u]),swap(num[p],num[now]);
    				break;
    			}
    			case 'A':{
    				cout<<getrk(to[u])-1<<'
    ';
    				break;
    			}
    			case 'Q':{
    				cout<<getval(u)<<'
    ';
    				break;
    			}
    		}
    	}
    }
    
  • 相关阅读:
    1132: 零起点学算法39——多组测试数据(a+b)
    1131: 零起点学算法38——求阶乘和
    1130: 零起点学算法37——求阶乘
    1129: 零起点学算法36——3n+1问题
    1128: 零起点学算法35——再求多项式(含浮点)
    1127: 零起点学算法34——继续求多项式
    1126: 零起点学算法33——求多项式
    Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化
    Netty源码分析(前言, 概述及目录)
    基于HTK语音工具包进行孤立词识别的使用教程
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/10366309.html
Copyright © 2011-2022 走看看