URAL 1439. Battle with You-Know-Who treap树

题目来源:URAL 1439. Battle with You-Know-Who

题意:开始有数列1, 2, 3, ... L k输出第k大的数 D k删除第k大的数

思路:treap树插入删除的数 每次二分查找第k大的数为mid 查询treap小于等于mid的数有y个 那么mid应该是第mid-y大的数 与k比较 继续二分

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;

const int maxm = 100010;
int ch[maxm][2], r[maxm], val[maxm], sum[maxm], num[maxm], cnt, root;

void Node(int &rt, int x){
    rt = ++cnt;
    ch[rt][0] = ch[rt][1] = 0;
    r[rt] = rand();
    val[rt] = x;
    if(cnt > 1)
    {
		sum[rt] = 1;
    	num[rt] = 1;
    }
    else
    {
    	sum[rt] = 0;
    	num[rt] = 0;
    }
}
void maintain(int rt){

    sum[rt] = sum[ch[rt][0]]+sum[ch[rt][1]]+num[rt];
}
void init()
{
	ch[0][0] = ch[0][1] = 0;
	r[0] = (1LL<<31)-1;
	val[0] = 0;
	sum[0] = 0;
	cnt = 0;
	root = 0;
	Node(root, 2000000001);
}

void rotate(int &rt, int d){
    int k = ch[rt][d^1]; ch[rt][d^1] = ch[k][d]; ch[k][d] = rt;
    maintain(rt); maintain(k); rt = k;
}

void insert(int &rt, int x){
    if(!rt){
        Node(rt, x);
        return;
    }
    else{
        if(x == val[rt])
            num[rt]++;
        else
        {
            int d = x < val[rt] ? 0 : 1;
            insert(ch[rt][d], x);
            if(r[ch[rt][d]] < r[rt]) rotate(rt, d^1);
        }
    }
    maintain(rt);
}

/*void remove(int &rt, int x){
    if(val[rt] == x){
        val[rt]--;
        if(!val[rt]){
            if(!ch[rt][0] && !ch[rt][1])
            {
                rt = 0;
                return;
            }
            else{
                int d = r[ch[rt][0]] > r[ch[rt][1]] ? 1 : 0;
                rotate(rt, d);
                remove(ch[rt][d], x);
            }
            else{

            }
        }
    }
    else
        remove(ch[rt][x>val[rt]], x);
    maintain(rt);
}*/

int kth(int rt, int k){
    if(rt == 0)
    	return 0;
	if(val[rt] <= k)
		return sum[ch[rt][0]]+num[rt]+kth(ch[rt][1], k);
	return kth(ch[rt][0], k);

}

int main()
{
	int n, m;
    while(scanf("%d %d", &n, &m) != EOF)
    {
    	init();
        while(m--)
        {
        	char s[10];
        	int x;
        	scanf("%s %d", s, &x);
        	int l = 1, r = n, ans;
        	//printf("****%d\n", kth(root, 10));
    		while(l < r)
        	{
        		int mid = (l + r) >> 1;
				int y = kth(root, mid);
        		if(x > mid-y)
        		{
	        		l = mid+1;
	        		ans = mid+1;
	        	}
	        	else
	        	{
        			r = mid;
        		}
				//printf("***%d\n", y);
        	}
        	if(s[0] == 'L')
        	{
				printf("%d\n", l);
	        }
	        else
        	{
        		//int y = kth(root, x);
				insert(root, l);
        	}
        }
    }
    return 0;
}
时间: 2024-10-12 03:48:51

URAL 1439. Battle with You-Know-Who treap树的相关文章

Treap树

(a) ①根据堆性质以每个结点为根的子树的最小优先级都是在子树的根上.②根据二叉搜索树性质,以每个节点的根的子树的左子树<右子树. 根据这两点根和左右子树都是被唯一确定,因此能够确定整棵树. (b)Treap树是二叉查找树的一种,而二叉查找树期望高度为O(lgn),所以treap期望高度为O(lgn). (c)代码如下: //13-4 Treap树 #include <iostream> #include <time.h> using namespace std; #defi

bzoj2141 树状数组套Treap树

题目大意是在能够改变两个数的位置的情况下计算逆序对数 这因为是动态记录逆序对 本来单纯逆序对只要用树状数组计算即可,但这里因为更新,所以利用TReap树的删点和增加点来进行更新 大致是把每个树状数组所管理的点都放在对应的Treap树下, 这样x-=lowbit(x)下来,正好访问到是所有比他小范围下的点了 然后根据每棵访问到的Treap树有多少个节点是比当前值小的即可 每次交换ai , aj , (i<j)只要考虑(i,j)范围内比ai大的数,比aj小的数,然后加加减减即可 如果ai!=aj也是

Noi2004郁闷的出纳员-treap树

treap树只需要单旋,可以写在一个函数中.当需要删除某点时只需不断将这个点下旋知道它只有少于一个的儿子,让他的 儿子 或者 空 取代它.插入时先插入,然后从底下向上通过旋转维护堆的性质.下面附标程: 1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 struct Node{ 7 int ch[2

treap树模板

1 ///treap树模板 2 typedef struct Node ///节点的结构体 3 { 4 Node *l,*r; 5 int val,pri; ///节点的值和优先级 6 int sz; ///节点子树的节点数 7 Node(int x) ///初始化节点 8 { 9 l=r=NULL; 10 val=x; 11 pri=rand(); 12 sz=1; 13 } 14 }Node; 15 Node *root; 16 17 int Tsize(Node *T) ///计算子树的叶

poj 1442 Black Box (treap树入门题)

1 /**************************************************** 2 题目: Black Box(poj 1442) 3 链接: http://poj.org/problem?id=1442 4 题意: 给n个数,m个询问,对第i数个询问前Xi个数中第 5 i小的是那个数. 6 算法: treap树 7 *****************************************************/ 8 #include<iostream

POJ 1442 Black Box(treap树)

题目链接:点击打开链接 思路:treap树模板题, 可以动态维护一个有序表, 支持在O(logN)的时间内完成插入.删除一个元素和查找第K大元素的任务. 当然, treap树能做到的还远远不止这些, 常常与其他数据结构嵌套. treap树是一种平衡二叉搜索树, 既满足堆的条件, 又满足排序二叉树的条件. 细节参见代码: #include <cstdio> #include <cstring> #include <algorithm> #include <iostr

6天通吃树结构—— 第三天 Treap树

原文:6天通吃树结构-- 第三天 Treap树 我们知道,二叉查找树相对来说比较容易形成最坏的链表情况,所以前辈们想尽了各种优化策略,包括AVL,红黑,以及今天 要讲的Treap树. Treap树算是一种简单的优化策略,这名字大家也能猜到,树和堆的合体,其实原理比较简单,在树中维护一个"优先级“,”优先级“ 采用随机数的方法,但是”优先级“必须满足根堆的性质,当然是“大根堆”或者“小根堆”都无所谓,比如下面的一棵树: 从树中我们可以看到: ①:节点中的key满足“二叉查找树”. ②:节点中的“优

Treap树模板hdu-4585

目录 例题:hdu 4585 Treap树 1.Treap树的唯一性 2.Treap树的平衡问题 3.Treap树的数据结构 4.Treap树的插入 5.插入过程中维护堆的过程中用到的旋转 6.寻找第k大的数 O(logn) 7.查询某个数的名次 O(logn) 8.hdu 4585 AC代码 例题:hdu 4585 Treap树 是一种简单的平衡二叉搜索树. 二叉搜索树的每一个节点都有一个键值,除此之外Treap树为每个节点人为添加了一个称之为优先级的权值.对于键值来说,这是一棵二叉搜索树,对

c++之路进阶——treap树(普通平衡树)

4543 普通平衡树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 大师 Master 题解 题目描述 Description 这是一道水题 顺便祝愿LEZ和ZQQ 省选AKAKAK 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数,因输出最小的排名)4. 查询排名为x的数5. 求x的前驱(前驱定义为小于x,且最大的数)6. 求x的后继(后继定义为大