BZOJ 1861 [Zjoi2006]Book 书架 ——Splay

【题目分析】

模板题目。

首尾两个虚拟结点,十分方便操作。

【代码】

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>

#include <map>
#include <set>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>

using namespace std;

#define maxn 500005
#define inf 0x3f3f3f3f
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define L ch[o][0]
#define R ch[o][1] 

void Finout()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    #endif
}

int Getint()
{
    int 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;

struct Bit_Tree{
	int a[maxn],b[maxn];
	void add(int x,int y,int z)
	{
		for (int i=x;i<=n;i+=i&(-i)) b[i]+=z;
		for (int i=y+1;i<=n;i+=i&(-i)) b[i]-=z;
		for (int i=x;i<=n;i+=i&(-i)) a[i]+=(n-x)*z;
		for (int i=y+1;i<=n;i+=i&(-i)) a[i]-=(n-y-1)*z;
	}
	int getsum(int x)
	{
		int ret=0,tmp=0;
		for (int i=x;i;i-=i&(-i)) ret+=a[i];
		for (int i=x;i;i-=i&(-i)) tmp+=b[i];
		return ret-(n-x-1)*tmp;
	}
	void init()
	{
		memset(a,0,sizeof a);
		memset(b,0,sizeof b);
	}
}t;

int rt=0,a[maxn],s,T,id[maxn],cnt=0;
char opt[10];
int num[maxn],ch[maxn][2],siz[maxn],fa[maxn],list[maxn];

void update(int o)
{
	siz[o]=siz[L]+siz[R]+1;
}

void rot(int x,int &k)
{
//	cout<<"rot"<<x<<endl;
    int y=fa[x],z=fa[y],l,r;
    if (ch[y][0]==x) l=0; else l=1;
    r=l^1;
    if (y==k) k=x;
    else
    {
        if (ch[z][0]==y) ch[z][0]=x;
        else ch[z][1]=x;
    }
    fa[x]=z;
    fa[y]=x;
    fa[ch[x][r]]=y;
    ch[y][l]=ch[x][r];
    ch[x][r]=y;
    update(y); update(x);
}

void splay(int x,int &k)
{
    int y,z;
    while (x!=k)
    {
        y=fa[x];z=fa[y];
        if (y!=k)
        {
            if ((ch[z][0]==y)^(ch[y][0]==x)) rot(x,k);
            else rot(y,k);
        }
        rot(x,k);
    }
}

void ins(int & o,int x,int lst)
{
	if (!o)
	{
		o=++cnt;
		fa[o]=lst;
		num[o]=x;
		siz[o]=1;
		list[o]=a[x-1];
		splay(o,rt);
		return ;
	}
	if (x<num[o]) ins(ch[o][0],x,o);
	else ins(ch[o][1],x,o);
	update(o);
}

int find(int o,int x)
{
//	cout<<"qnum"<<num[o]<<" "<<x<<endl;
	if (siz[L]+1==x) return o;
	if (siz[L]>=x) return find(L,x);
	else return find(R,x-siz[L]-1);
}

void print(int o)
{
	if (!o) return ;
	print(L);
//	cout<<"now is "<<o<<endl;
//	cout<<L<<" "<<R<<endl;
//	cout<<num[o]<<" "<<siz[o]<<endl;
	cout<<num[o]<<" ";
	print(R);
}

void Mov(int o,int k)
{
	splay(o,rt);
	int pre=find(rt,siz[L]),nxt=find(rt,siz[L]+2);
	splay(pre,rt); splay(nxt,ch[rt][1]);
	ch[nxt][0]=0; fa[o]=0;
	update(nxt); update(pre);
	splay(nxt,rt);
	pre=find(rt,k-1);nxt=find(rt,k);
	splay(pre,rt); splay(nxt,ch[rt][1]);
	ch[nxt][0]=o; fa[o]=nxt;
	splay(o,rt);
}

int main()
{
    Finout();
    scanf("%d%d",&n,&m);
    F(i,1,n) scanf("%d",&a[i]),id[a[i]]=i+1;
    F(i,0,n+1) ins(rt,i,0);
//    print(rt);
//    cout<<rt<<endl;
    F(i,1,m)
    {
//    	print(rt);
//    	cout<<endl;
    	scanf("%s",opt);
    	scanf("%d",&s);
    	if (opt[0]==‘Q‘)
		{
//			cout<<"QUERY"<<endl;
			printf("%d\n",a[find(rt,s+1)-1]);
		}
    	else if (opt[0]==‘A‘)
    	{
//    		cout<<"ASK"<<endl;
    		splay(id[s],rt);
    		printf("%d\n",siz[ch[rt][0]]-1);
		}
		else if (opt[0]==‘T‘)
		{
//			cout<<"TOP"<<endl;
			Mov(id[s],1+1);
		}
		else if (opt[0]==‘B‘)
		{
//			cout<<"BOT"<<endl;
			Mov(id[s],n+1);
		}
		else
		{
			T=Getint();
			splay(id[s],rt);
			int tmp=siz[ch[rt][0]];
			Mov(id[s],tmp+T+1);
		}
	}
}

  

时间: 2024-11-08 11:30:59

BZOJ 1861 [Zjoi2006]Book 书架 ——Splay的相关文章

BZOJ 1861: [Zjoi2006]Book 书架 splay

1861: [Zjoi2006]Book 书架 Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置.不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1.X或X+1本

BZOJ 1861: [Zjoi2006]Book 书架 (splay)

1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1453  Solved: 822[Submit][Status][Discuss] Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位

bzoj1861 [Zjoi2006]Book 书架——splay

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1861 发现自己想splay的时候总是纠结那个点权是什么,因为splay原本是二分查找树... 但其实splay已经不是维护点权大小顺序的,它的最大作用就在于无论怎样旋转都保持着中序遍历这个相对位置不变: 所以很对应这道题,用splay进行各种操作的同时书的摆放顺序是不变的: 假设出一个'1'点.一个'n+1'点方便操作,所以整体+1: 这个建树的方法不错呢. 代码如下: #include<

【BZOJ 1861】Book 书架

Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置.不过小T的记忆力是非常好的,所以每次放书的时候至少能够将那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1.X或X+1本书. 当然也有特殊情况,比如在看书的时候突然电话

[题解]bzoj 1861 Book 书架 - Splay

1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1396  Solved: 803[Submit][Status][Discuss] Description 小T有一个很大的书柜.这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列.她用1到n的正整数给每本书都编了号. 小T在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本.由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位

[Zjoi2006]Book 书架

pre.cjk { font-family: "Droid Sans Fallback", monospace } p { margin-bottom: 0.25cm; line-height: 120% } a:link { } 1861: [Zjoi2006]Book 书架 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 1581  Solved: 884[Submit][Status][Discuss] Description 小T有一

BZOJ 1003: [ZJOI2006]物流运输trans

二次联通门 : BZOJ 1003: [ZJOI2006]物流运输trans /* BZOJ 1003: [ZJOI2006]物流运输trans Spfa + Dp Spfa预处理出i到j天的最小花费 然后N^2 dp即可 */ #include <cstdio> #include <iostream> #include <cstring> #include <queue> #define INF 1e6 const int BUF = 12312313;

BZOJ 1861 ZJOI 2006 Book 书架 Splay

题目大意:有一个书架,现在需要经常改变这些书的位置,每次询问一本书在哪或者第几本书是什么. 思路:赤裸裸的Splay,只是有些小事需要注意.因为他有的时候问你一个书在哪,这个事情不能只在Splay中就能解决,我们需要辅助他解决.注意到操作中没有加入书的操作,也就是书的总数并不会变化,而且Splay的过程中只是指针的变动,所以不会有点发生变化,所以在一开始建树的时候维护一个数组,表示这本书在Splay中的节点,这样我们就能快速的找到任意一本书的节点.询问一本书的排名的时候,我们需要先找到这个节点,

BZOJ 1862: [Zjoi2006]GameZ游戏排名系统 Splay

Splay的基本操作,比较繁琐..... 有个一坑点,sorce会超int 1862: [Zjoi2006]GameZ游戏排名系统 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 913  Solved: 343 [Submit][Status][Discuss] Description GameZ为他们最新推出的游戏开通了一个网站.世界各地的玩家都可以将自己的游戏得分上传到网站上.这样就可以看到自己在世界上的排名.得分越高,排名就越靠前.当两个玩家