HDU 4006 求第k大数 treap

裸题,瞬秒。。

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
using namespace std;
#define L(id) tree[id].ch[0]
#define R(id) tree[id].ch[1]
#define Size(id) tree[id].size
#define Father(id) tree[id].fa
#define Val(id) tree[id].val
#define ll int
ll Mid(ll x,ll y){return (x+y)>>1;}
#define N 30100

ll a[N], n;
int ch[N][2],val[N],counts[N],r[N],size[N],tot,root;
int Newnode(int &rt,int v)
{
	rt=++tot;
	val[rt]=v;
	ch[rt][0]=ch[rt][1]=0;
	counts[rt]=size[rt]=1;
	r[rt]=rand();
	return rt;
}
inline void PushUp(int rt)
{
	size[rt]=size[ch[rt][0]]+size[ch[rt][1]]+counts[rt];
}
void Rotate(int &x,int kind)
{
	int y=ch[x][kind^1];
	ch[x][kind^1]=ch[y][kind];
	ch[y][kind]=x;
	PushUp(x);PushUp(y);
	x=y;
}
int Insert(int &rt,int v)
{
	if(rt==0)
		return Newnode(rt,v);
	int ans;
	if(v==val[rt]) counts[rt]++, ans = rt;
	else
	{
		int kind=(v>val[rt]);
		ans = Insert(ch[rt][kind],v);
		if(r[ch[rt][kind]]<r[rt])
			Rotate(rt,kind^1);
	}
	PushUp(rt);
	return ans;
}
int select(int rt,int k)
{
	if(size[ch[rt][0]]>=k) return select(ch[rt][0],k);
	if(size[ch[rt][0]]+counts[rt]>=k) return val[rt];
	return select(ch[rt][1],k-size[ch[rt][0]]-counts[rt]);
}
void remove(int &rt,int v)
{
	if(val[rt]==v)
	{
		if(counts[rt]>1)
			counts[rt]--;
		else if(!ch[rt][0]&&!ch[rt][1])
		{rt=0;return ;}
		else
		{
			int kind=r[ch[rt][0]]<r[ch[rt][1]];
			Rotate(rt,kind);
			remove(rt,v);
		}
	}
	else remove(ch[rt][v>val[rt]],v);
	PushUp(rt);
}
void Init()
{
	ch[0][0]=ch[0][1]=0;
	size[0]=counts[0]=val[0]=0;
	tot=root=0;
	r[0]=(1LL<<31)-1;
	Newnode(root,2000000001);
}
int q[N];
char s[2];
int main(){
	int que, i, j, k, l, r;
	while(~scanf("%d %d",&n,&que)){
		Init();
		while(n--){
			scanf("%s",s);
			if(s[0]=='I')scanf("%d",&l),Insert(root,-l);
			else printf("%d\n",-select(root,que));
		}
	}
	return 0;
}

HDU 4006 求第k大数 treap,布布扣,bubuko.com

时间: 2024-10-21 05:29:29

HDU 4006 求第k大数 treap的相关文章

poj 2985 The k-th Largest Group 求第K大数 Treap, Binary Index Tree, Segment Tree

题目链接:点击打开链接 题意:有两种操作,合并集合,查询第K大集合的元素个数.(总操作次数为2*10^5) 解法: 1.Treap 2.树状数组 |-二分找第K大数 |-二进制思想,逼近第K大数 3.线段树 4.... Treap模板(静态数组) #include <math.h> #include <time.h> #include <stdio.h> #include <limits.h> #include <stdlib.h> const

hdu2852 KiKi&#39;s K-Number 树状数组求第k大数

//再求第k大数时只需要getsum(b-1)<getsum(a)+k<=getsum(b) //b就是a的第k大数 //又gesum(b-1)<=getsum(b)则可以用二分查找来做 #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=100010; int tree[maxn]; int lowbit(int i) {

普林斯顿大学算法课 Algorithm Part I Week 3 求第K大数 Selection

问题 给定N个元素的数组,求第k大的数. 特例当k=0时,就是求最大值,当k=N-1时,就是求最小值. 应用顺序统计求top N排行榜 基本思想 使用快速排序方法中的分区思想,使得a[k]左侧没有更小的数,右侧没有更大的数 性能 快速选择算法的复杂度是N. 最坏情况下的复杂度是1/2N^2,但是可以通过预先洗牌来防止出现最坏情况 public static Comparable select(Comparable[] a, int k) { StdRandom.shuffle(a); int l

[nowCoder] 两个不等长数组求第K大数

给定两个有序数组arr1和arr2,在给定一个整数k,返回两个数组的所有数中第K小的数.例如:arr1 = {1,2,3,4,5};arr2 = {3,4,5};K = 1;因为1为所有数中最小的,所以返回1: arr1 = {1,2,3};arr2 = {3,4,5,6};K = 4;因为3为所有数中第4小的数,所以返回3: 要求:如果arr1的长度为N,arr2的长度为M,时间复杂度请达到O(log(min{M,N})). 这题目的难度在于时间复杂度请达到O(log(min{M,N})),参

HDU 5008 求第k小子串

本题要求第k小的distinct子串,可以根据height数组,二分出这个第k小子串所在后缀的位置信息.由于题目要求子串起始下标尽可能小.所以再在rank数组中,二分出与当前后缀LCP大于等于所求子串长度的范围.通过RMQ求出这个范围中最小的sa. 1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 #include <string> 5 #include <string

求第k大数

题意:输入n个整数和一个正整数k(k>=1&&k<=n),输出这些数从小到大排序后的第k个(例如,k=1就是最小值).n<=10^7. 分析:由于n比较大如果先排序后求解,那时间复杂度有点高了n*log(n),然后hash的话数组开不了,用什么方法求解呢?我这里给出一种用快速排序的方法解决,当然这就需要对快速排序的原理理解了,自己百度吧! 代码实现: #include<iostream> #include<cstdio> #include<c

HDU 4006 The kth great number (基本算法-水题)

The kth great number Problem Description Xiao Ming and Xiao Bao are playing a simple Numbers game. In a round Xiao Ming can choose to write down a number, or ask Xiao Bao what the kth great number is. Because the number written by Xiao Ming is too mu

HDU 2639 01背包求第k大

Bone Collector II Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3718    Accepted Submission(s): 1903 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took par

[csu/coj 1080]划分树求区间前k大数和

题意:从某个区间内最多选择k个数,使得和最大 思路:首先题目给定的数有负数,如果区间前k大出现负数,那么负数不选和更大,于是对于所有最优选择,负数不会出现,所以用0取代负数,问题便转化为区间的前k大数和. 划分树: [1  6  3  8  5  4  7  2] [6  8  5  7][1  3  4  2] [8  7][6  5][3  4][1  2] [8][7][6][5][4][3][2][1] 把快排的结果从上至下依次放入线段树,就构成了划分树,划分的意思就是选定一个数,把原序