zoukankan      html  css  js  c++  java
  • [ZJOI2006]Book书架

    Description
    Sally有一个很大的书柜。这个书柜的构造有些独特,即书柜里的书是从上至下堆放成一列。她用1到n的正整数给每本书都编了号。Sally在看书的时候,每次取出一本书,看完后放回书柜然后再拿下一本。由于这些书太有吸引力了,所以她看完后常常会忘记原来是放在书柜的什么位置。不过Sally的记忆力是非常好的,所以每次放书的时候至少能够那本书放在拿出来时的位置附近,比如说她拿的时候这本书上面有X本书,那么放回去时这本书上面就只可能有X-1、X或X+1本书。当然也有特殊情况,比如在看书的时候突然电话响了或者有朋友来访。这时候粗心的Sally会随手把书放在书柜里所有书的最上面或者最下面,然后转身离开。久而久之,Sally的书柜里的书的顺序就会越来越乱,找到特定的编号的书就变得越来越困难。于是她想请你帮她编写一个图书管理程序,处理她看书时的一些操作,以及回答她的两个提问:(1)编号为X的书在书柜的什么位置;(2)从上到下第i本书的编号是多少。

    Input
    第一行有两个数n,m,分别表示书的个数以及命令的条数;第二行为n个正整数:第i个数表示初始时从上至下第i个位置放置的书的编号;第三行到m+2行,每行一条命令。命令有5种形式:
    1. Top S——表示把编号为S的书房在最上面。
    2. Bottom S——表示把编号为S的书房在最下面。
    3. Insert S T——T∈{-1,0,1},若编号为S的书上面有X本书,则这条命令表示把这本书放回去后它的上面有X+T本书;
    4. Ask S——询问编号为S的书的上面目前有多少本书。
    5. Query S——询问从上面数起的第S本书的编号。
    n,m<=80000

    Output
    对于每一条Ask或Query语句你应该输出一行,一个数,代表询问的答案。

    Sample Input
    10 10
    1 3 2 7 5 8 10 4 9 6
    Query 3
    Top 5
    Ask 6
    Bottom 3
    Ask 3
    Top 6
    Insert 4 –1
    Query 5
    Query 2
    Ask 2

    Sample Output
    2
    9
    9
    7
    5
    3


    这题多两个操作,取出最靠右的点和最靠左的点。insert操作把点往左挪或往右挪,Top/Down放到最上面或最下面就好了,具体操作可以看下代码

    关于本人splay代码操作详解请参考浅谈算法——splay

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x>=10)     print(x/10);
    	putchar(x%10+'0');
    }
    const int N=8e4;
    struct Splay{
    	#define T(x) (tree[f[x]][1]==x)
    	int tree[N+10][2],f[N+10],size[N+10],val[N+10];
    	int root,len;
    	void updata(int x){size[x]=size[tree[x][0]]+size[tree[x][1]]+1;}
    	void build(int n){
    		for (int i=1;i<=n;i++)	val[i]=read();
    		for (int i=1;i<n;i++)	f[val[i]]=val[i+1],tree[val[i+1]][0]=val[i],size[val[i]]=i;
    		size[root=val[n]]=n;
    	}
    	void move(int x){
    		int fa=f[x],son=tree[x][T(x)^1];
    		tree[x][T(x)^1]=fa;
    		tree[fa][T(x)]=son;
    		if (son)	f[son]=fa;
    		f[x]=f[fa];
    		if (f[x])	tree[f[x]][T(fa)]=x;
    		f[fa]=x;
    		updata(fa),updata(x);
    	}
    	void splay(int x){
    		while (f[x]){
    			if (f[f[x]])	T(x)==T(f[x])?move(f[x]):move(x);
    			move(x);
    		}
    		root=x;
    	}
    	int get_pre(){
    		int x=tree[root][0];
    		while (tree[x][1])	x=tree[x][1];
    		return x;
    	}
    	int get_suc(){
    		int x=tree[root][1];
    		while (tree[x][0])	x=tree[x][0];
    		return x;
    	}
    	int get_front(){
    		int x=root;
    		while (tree[x][0])	x=tree[x][0];
    		return x;
    	}
    	int get_last(){
    		int x=root;
    		while (tree[x][1])	x=tree[x][1];
    		return x;
    	}
    	void Delete(int x){
    		splay(x);
    		if (!(tree[x][0]&&tree[x][1])){
    			f[root=tree[x][0]+tree[x][1]]=0;
    			f[x]=tree[x][0]=tree[x][1]=size[x]=0;
    			return;
    		}
    		int i=get_pre();
    		splay(i);
    		f[tree[i][1]=tree[x][1]]=i;
    		f[x]=tree[x][0]=tree[x][1]=size[x]=0;
    		updata(i);
    	}
    	int find(int x,int i){
    		if (size[tree[i][0]]+1==x)	return i;
    		if (x<=size[tree[i][0]])	return find(x,tree[i][0]);
    		return find(x-size[tree[i][0]]-1,tree[i][1]);
    	}
    	void change(int x,int t){
    		Delete(x);
    		int i=t?get_last():get_front();
    		splay(i);
    		f[tree[i][t]=x]=i;
    		size[x]++,size[i]++;
    	}
    	void insert(int x,int t){
    		splay(x);
    		int i=t?get_suc():get_pre();
    		Delete(x);
    		splay(i);
    		f[tree[x][t]=tree[i][t]]=x;
    		f[tree[i][t]=x]=i;
    		size[x]=size[tree[x][t]]+1;
    		size[i]++;
    	}
    	void Ask(int x){
    		splay(x);
    		printf("%d
    ",size[tree[x][0]]);
    	}
    	void query(int x){printf("%d
    ",find(x,root));}
    }T;
    char s[10];
    int main(){
    	int n=read(),m=read();
    	T.build(n);
    	for (int i=1;i<=m;i++){
    		scanf("%s",s);
    		if (s[0]=='I'){
    			int x=read(),t=read();
    			if (t)	T.insert(x,t==1);
    		}
    		if (s[0]=='T')	T.change(read(),0);
    		if (s[0]=='B')	T.change(read(),1);
    		if (s[0]=='A')	T.Ask(read());
    		if (s[0]=='Q')	T.query(read());
    	}
    	return 0;
    }
    
  • 相关阅读:
    c# 用System.Net 读取网页源代码 1
    最新影视论坛
    【待续】翻译:jQuery Mobile: 他能为你做什么?
    【转】ASP.NET MVC 3.0 新特性之View
    强烈推荐:纯JAVASCRIPT图表动画插件Highcharts Examples
    [翻译]帮助文档jQuery 选择器
    【转】C# DateTime Format Examples [C#日期格式化]
    【转载】LINQ to SQL之一
    【转】ASP.NET MVC 3.0 新特性之Controller
    强烈推荐:JAVASCRIPT图片相册插件
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/9479041.html
Copyright © 2011-2022 走看看