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

    [BZOJ1861][Zjoi2006]Book 书架

    试题描述

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

    输入

    第一行有两个数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本书的编号。

    输出

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

    输入示例

    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

    输出示例

    2
    9
    9
    7
    5
    3

    数据规模及约定

    100%的数据,n,m < = 80000

    题解

    让每个节点的编号与它在伸展树中的编号一致,查找排名时利用子树大小,查询某节点排名时把它伸展到根就好了。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 80010
    struct Node {
    	int siz;
    	Node() {}
    } ns[maxn];
    int ToT, fa[maxn], ch[2][maxn], id[maxn];
    void maintain(int o) {
    	ns[o].siz = 1;
    	for(int i = 0; i < 2; i++) if(ch[i][o])
    		ns[o].siz += ns[ch[i][o]].siz;
    	return ;
    }
    void build(int& o, int l, int r) {
    	if(l > r) return ;
    	int mid = l + r >> 1; o = id[mid];
    	build(ch[0][o], l, mid - 1); build(ch[1][o], mid + 1, r);
    	if(ch[0][o]) fa[ch[0][o]] = o;
    	if(ch[1][o]) fa[ch[1][o]] = o;
    	return maintain(o);
    }
    void rotate(int u) {
    	int y = fa[u], z = fa[y], l = 0, r = 1;
    	if(z) ch[ch[1][z]==y][z] = u;
    	if(ch[1][y] == u) swap(l, r);
    	fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
    	ch[l][y] = ch[r][u]; ch[r][u] = y;
    	maintain(y); maintain(u);
    	return ;
    }
    void splay(int u) {
    	while(fa[u]) {
    		int y = fa[u], z = fa[y];
    		if(z) {
    			if(ch[0][y] == u ^ ch[0][z] == y) rotate(u);
    			else rotate(y);
    		}
    		rotate(u);
    	}
    	return ;
    }
    int splitl(int u) {
    	splay(u);
    	int tmp = ch[0][u];
    	fa[tmp] = ch[0][u] = 0;
    	maintain(u);
    	return tmp;
    }
    int splitr(int u) {
    	splay(u);
    	int tmp = ch[1][u];
    	fa[tmp] = ch[1][u] = 0;
    	maintain(u);
    	return tmp;
    }
    int merge(int a, int b) {
    	if(!a) return maintain(b), b;
    	if(!b) return maintain(a), a;
    	while(ch[1][a]) a = ch[1][a];
    	splay(a);
    	ch[1][a] = b; fa[b] = a;
    	return maintain(a), a;
    }
    int getrt() {
    	int u = 1; while(fa[u]) u = fa[u];
    	return u;
    }
    int Find(int o, int k) {
    	if(!o) return 0;
    	int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
    	if(k == ls + 1) return o;
    	if(k > ls + 1) return Find(ch[1][o], k - ls - 1);
    	return Find(ch[0][o], k);
    }
    
    int main() {
    	int n = read(), q = read();
    	for(int i = 1; i <= n; i++) id[i] = read();
    	int tmp = 0; build(tmp, 1, n);
    	
    	int tq = q;
    	while(q--) {
    		char cmd[10]; scanf("%s", cmd);
    		if(cmd[0] == 'T') {
    			int mrt = read(), lrt = splitl(mrt), rrt = splitr(mrt);
    			lrt = merge(lrt, rrt); merge(mrt, lrt);
    		}
    		if(cmd[0] == 'B') {
    			int mrt = read(), lrt = splitl(mrt), rrt = splitr(mrt);
    			lrt = merge(lrt, rrt); merge(lrt, mrt);
    		}
    		if(cmd[0] == 'I') {
    			int mrt = read(), t = read(), rk, lrt, rrt;
    			if(!t) continue;
    			splay(mrt); rk = (ch[0][mrt] ? ns[ch[0][mrt]].siz : 0) + 1 + t;
    			if(rk < 1 || rk > n) continue; rk = Find(getrt(), rk);
    			if(t < 0) {
    				lrt = splitl(rk); splitl(mrt); rrt = splitr(mrt);
    				lrt = merge(lrt, mrt); lrt = merge(lrt, rk); merge(lrt, rrt);
    			}
    			else {
    				lrt = splitl(mrt); splitl(rk); rrt = splitr(rk);
    				lrt = merge(lrt, rk); lrt = merge(lrt, mrt); merge(lrt, rrt);
    			}
    		}
    		if(cmd[0] == 'A') {
    			int u = read();
    			splay(u);
    			printf("%d
    ", ch[0][u] ? ns[ch[0][u]].siz : 0);
    		}
    		if(cmd[0] == 'Q') printf("%d
    ", Find(getrt(), read()));
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    JQuery实现表格的全选和反选,以及分页勾选保存(laypage插件分页的使用)
    js之如何获取css样式
    JS正则表达式一些基本使用、验证、匹配、正则匹配时一个变量
    jQuery绑定事件的四种方式
    console命令详解
    实现a标签中的各种点击(onclick)事件的方法
    用JSON.parse和eval出现的问题
    js 将json对象转成字符串
    iOS主流机型更新
    * -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]’
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6250201.html
Copyright © 2011-2022 走看看