ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

书架

2022-07-02 17:04:54  阅读:150  来源: 互联网

标签:return 书架 int 元素 wh inline size


link

平衡树的一点小变通。

要求支持一些操作:询问序列第k个元素是什么,询问元素k在序列中的位置,把一个元素放到序列最前面或最后面,交换两个元素(\(insert\) 操作说白了就是交换这个元素和它前面或后面的元素交换)。

第一个和最后一个还好,其它操作有点麻烦。问题就在于要把节点的点值和节点的编号挂钩,于是就想到用 \(pl[i]\) 来代表元素i对应的节点,在交换元素的时候就把pl对应的元素交换,把对应节点的点权交换一下即可。至于询问元素i在序列中的位置,直接暴力向上跳即可。

是要splay的,而且最好顺便splay一个随机节点。玄学方法过的。随机Splay主要是因为把元素丢到序列最前面和最后面的时候涉及到删除和插入操作。

#include<bits/stdc++.h>
//#define zczc
const int N=80010;
using namespace std;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline void swap(int &s1,int &s2){
	int s3=s1;s1=s2;s2=s3;
}

#define lc t[x].ch[0]
#define rc t[x].ch[1]
struct node{
	int id,size,ch[2],f;
}t[N];
int root;
inline void pushup(int x){
	t[x].size=t[lc].size+t[rc].size+1;
}
inline int build(int l,int r,int fa){
	//printf("now:%d %d\n",l,r);
	if(l>r)return 0;
	if(l==r)return t[l].f=fa,t[l].size=1,l;
	int x=l+r+1>>1;
	t[x].f=fa;
	lc=build(l,x-1,x);
	rc=build(x+1,r,x);
	pushup(x);
	return x;
}
inline int work(int x,int come){
	//printf("%d %d\n",x,come);
	return (x==root?0:work(t[x].f,x))+(come==rc?1+t[lc].size:0);
}
inline int find(int x,int kk){
	if(kk<0)return 0;
	//printf("now:%d %d\n",x,kk);
	if(kk<=t[lc].size)return find(lc,kk);
	if(kk==t[lc].size+1)return t[x].id;
	return find(rc,kk-t[lc].size-1);
}

inline void rotate(int x){
	int y=t[x].f;int z=t[y].f;int kk=t[y].ch[1]==x;int cd=t[x].ch[kk^1];
	if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].f=z;
	t[cd].f=y;t[y].ch[kk]=cd;
	t[x].ch[kk^1]=y;t[y].f=x;
	pushup(y);pushup(x);
	if(y==root)root=x;
}
inline void splay(int x){
	while(t[x].f){
		int y=t[x].f;int z=t[y].f;
		if(z)(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);
		rotate(x);
	}
	root=x;
}
void delete_(int x){
	while(lc!=0||rc!=0){
		if(lc&&rc)rotate(t[x].ch[rand()%2]);
		else if(lc)rotate(lc);
		else rotate(rc);
		//printf("%d %d\n",lc,rc);
	}
	int ff=t[x].f;
	t[ff].ch[t[ff].ch[1]==x]=0;
	while(ff)pushup(ff),ff=t[ff].f;
}
void put_l(int wh){
	int x=root;
	while(lc)x=lc;
	lc=wh;t[wh].f=x;
	while(x)pushup(x),x=t[x].f;
	return;
}
void put_r(int wh){
	int x=root;
	while(rc)x=rc;
	rc=wh;t[wh].f=x;
	while(x)pushup(x),x=t[x].f;
	return;
}
#undef lc
#undef rc

int m,n,pl[N];//pl:每本书对应哪个节点 

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	srand(time(0));
	
	read(m);read(n);
	for(int i=1;i<=m;i++){
		read(t[i].id);
		pl[t[i].id]=i;
	}
	root=build(1,m,0);
	int s1,s2;
	while(n--){
		char op[20];scanf("%s",op);
		switch(op[0]){
			case 'Q':
				read(s1);
				printf("%d\n",find(root,s1));
				break;
			case 'A':
				read(s1);s1=pl[s1];
				printf("%d\n",work(s1,t[s1].ch[1])-1);
				break;
			case 'B':
				read(s1);s1=pl[s1];
				delete_(s1);
				put_r(s1);
				//splay(s1);
				splay(rand()%m+1);
				break;
			case 'T':
				read(s1);s1=pl[s1];
				delete_(s1);put_l(s1);
				//splay(s1);
				splay(rand()%m+1);
				break;
			case 'I':
				read(s1);read(s2);
				if(s2==0)break;
				int ap=find(root,work(pl[s1],t[pl[s1]].ch[1])+s2);
				swap(pl[s1],pl[ap]);
				swap(t[pl[s1]].id,t[pl[ap]].id);
				break;
		}
	}
	
	return 0;
}

标签:return,书架,int,元素,wh,inline,size
来源: https://www.cnblogs.com/dai-se-can-tian/p/16437868.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有