社区讨论

Splay 求助,洛谷 AC,模拟赛 WA

P2596[ZJOI2006] 书架参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@lo7iifpf
此快照首次捕获于
2023/10/27 02:22
2 年前
此快照最后确认于
2023/10/27 02:22
2 年前
查看原帖
CPP
#include <bits/stdc++.h>
#define gc IO::fastgc()
#define pc(c) putchar(c)
typedef long long ll;typedef long long unsigned llu,ull;typedef long double lf;
using namespace std;
constexpr unsigned N=5e6+7;
int n,m;
ll p[N];
int pos[N];
int rcl[N],rtop;
struct Node{
	ll v;
	int s[2],p,sz;
	void init(ll vv,int pp){
		v=vv,
		s[0]=s[1]=0,
		p=pp,
		sz=1;
	}
}tr[N];
int rt,ncnt;
void out(int);
int newnode(){
	if(rtop){
		return rcl[rtop--];
	}
	return ++ncnt;
}
inline void pushup(int u){
	tr[u].sz=tr[tr[u].s[0]].sz+tr[tr[u].s[1]].sz+1;
}
inline void rotate(int x){
	int y=tr[x].p;
	int z=tr[y].p;
	int k=(tr[y].s[1]==x),p=(tr[z].s[1]==y);
	tr[z].s[p]=x,tr[x].p=z;
	tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y;
	tr[x].s[k^1]=y,tr[y].p=x;
	pushup(y),
	pushup(x);
}
inline void splay(int x,int k){
	while(tr[x].p!=k){
		int y=tr[x].p;
		int z=tr[y].p;
		if(z!=k){
			if((tr[y].s[1]==x)^(tr[z].s[1]==y)){
				rotate(x);
			}
			else{
				rotate(y);
			}
		}
		rotate(x);
	}
	if(!k){
		rt=x;
	}
}
int build(int l,int r){
	int mid=(l+r)>>1,u=newnode();
	tr[u].init(p[mid],0);
	pos[p[mid]]=u;
	if(l<=mid-1){
		tr[u].s[0]=build(l,mid-1),
		tr[tr[u].s[0]].p=u;
	}
	if(r>=mid+1){
		tr[u].s[1]=build(mid+1,r);
		tr[tr[u].s[1]].p=u;
	}
	pushup(u);
	return u;
}
inline int query(int x){
	int u=rt,s0;
	while(1){
		s0=tr[tr[u].s[0]].sz;
		if(s0+1==x){
			splay(u,0);
			return u;
		}
		else if(s0>=x){
			u=tr[u].s[0];
		}
		else{
			u=tr[u].s[1];
			x-=s0+1;
		}
	}
}
int ask(int p){
	splay(p,0);
	return tr[tr[rt].s[0]].sz;
}
void insert(int p,ll v){
	int x=query(p+1),y=query(p+2);
	splay(x,0),
	splay(y,x);
	tr[y].s[0]=newnode();
	tr[tr[y].s[0]].init(v,y);
	pos[v]=tr[y].s[0];
	pushup(y);
	pushup(x);
	splay(tr[y].s[0],0);
}
void del(int p){
	int ps=ask(p);
	int x=query(ps),y=query(ps+2);
	splay(x,0),
	splay(y,x);
	pos[tr[tr[y].s[0]].v]=-1;
	rcl[++rtop]=tr[y].s[0];
	tr[y].s[0]=0;
	pushup(y);
	pushup(x);
}
int main(){
	freopen("book.in","r",stdin),
	freopen("book.out","w",stdout);
	int s,t;
	static char op[17];
	scanf("%d%d",&n,&m);
	p[1]=p[n+2]=0;
	for(int i=2;i<=n+1;++i){
		scanf("%lld",p+i);
	}
	rt=build(1,n+2);
	while(m--){
		scanf("%s",op);
		switch(op[0]){
			case 'T': 
			case '1':{
				scanf("%d",&s);
				del(pos[s]);
				insert(0,s);
				break;
			}
			case 'B':
			case '2':{
				scanf("%d",&s);
				del(pos[s]);
				insert(n-1,s);
				break;
			}
			case 'I': 
			case '3':{
				scanf("%d%d",&s,&t);
				int np=ask(pos[s])+t;
				del(pos[s]);
				insert(np-1,s);
				break;
			}
			case 'A':
			case '4':{
				scanf("%d",&s);
				printf("%d\n",ask(pos[s])-1);
				break;
			}
			case 'Q':
			case '5':{
				scanf("%d",&s);
				printf("%lld\n",tr[query(s+1)].v);
				break;
			}
		}
	}
	return 0;
}
模拟赛的题就只是把范围加到 5×1055\times 10^5,操作改成 12345

回复

2 条回复,欢迎继续交流。

正在加载回复...