bzoj 3685: 普通van Emde Boas树

3685: 普通van Emde Boas树

Description

设计数据结构支持:
1 x  若x不存在,插入x
2 x  若x存在,删除x
3    输出当前最小值,若不存在输出-1
4    输出当前最大值,若不存在输出-1
5 x  输出x的前驱,若不存在输出-1
6 x  输出x的后继,若不存在输出-1
7 x  若x存在,输出1,否则输出-1

Input

第一行给出n,m 表示出现数的范围和操作个数
接下来m行给出操作
n<=10^6,m<=2*10^6,0<=x<n

Sample Input

10 11
1 1
1 2
1 3
7 1
7 4
2 1
3
2 3
4
5 3
6 2

Sample Output

1
-1
2
2
2
-1

Source

By Zky

题解:

vEB树是什么东东???。。。。

按照题目描述用线段树做就好了。。。。

按0~n划分区间,记录区间中存在的数的个数。

提一下前驱的找法:

对于x,在整个区间内找x-1,每次递归的两次区间,如果x-1在左区间,那么直接递归左区间,如果在右区间,判断右区间有无答案,没有的话则当前答案是左区间内的最大值。

后继的话找法差不多。。

#include<stdio.h>
#include<iostream>
using namespace std;
const int N=1000005;
#define p1 (p<<1)
#define p2 (p<<1|1)
int n,m,i,p,x,t[N<<2];
inline void read(int &v){
    char ch,fu=0;
    for(ch=‘*‘; (ch<‘0‘||ch>‘9‘)&&ch!=‘-‘; ch=getchar());
    if(ch==‘-‘) fu=1, ch=getchar();
    for(v=0; ch>=‘0‘&&ch<=‘9‘; ch=getchar()) v=v*10+ch-‘0‘;
    if(fu) v=-v;
}
void update(int l,int r,int x,int y,int p)
{
	if(l==r)
	{
		t[p]=y;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid) update(l,mid,x,y,p1);else update(mid+1,r,x,y,p2);
	t[p]=t[p1]+t[p2];
}
int Min(int l,int r,int p)
{
	if(!t[p]) return -1;
	if(l==r) return l;
	int mid=(l+r)>>1;
	if(t[p1]) return Min(l,mid,p1);else return Min(mid+1,r,p2);
}
int Max(int l,int r,int p)
{
	if(!t[p]) return -1;
	if(l==r) return l;
	int mid=(l+r)>>1;
	if(t[p2]) return Max(mid+1,r,p2);else return Max(l,mid,p1);
}
int find(int l,int r,int x,int p)
{
	if(!t[p]) return -1;
	if(l==r) return 1;
	int mid=(l+r)>>1;
	if(x<=mid) return find(l,mid,x,p1);else return find(mid+1,r,x,p2);
}
int pre(int l,int r,int x,int p)
{
	if(x<0) return -1;
	if(!t[p]) return -1;
	if(l==r) return l;
	int mid=(l+r)>>1;
	if(x<=mid) return pre(l,mid,x,p1);else
	{
		int tmp=pre(mid+1,r,x,p2);
		if(tmp==-1) return Max(l,mid,p1);else return tmp;
	}
}
int last(int l,int r,int x,int p)
{
	if(x>n) return -1;
	if(!t[p]) return -1;
	if(l==r) return l;
	int mid=(l+r)>>1;
	if(x>mid) return last(mid+1,r,x,p2);else
	{
		int tmp=last(l,mid,x,p1);
		if(tmp==-1) return Min(mid+1,r,p2);else return tmp;
	}
}
int main()
{
	read(n),read(m);
	for(i=1;i<=m;i++)
	{
		read(p);
		if(p==1)
		{
			read(x);
			update(0,n,x,1,1);
		} else
		if(p==2)
		{
			read(x);
			update(0,n,x,0,1);
		} else
		if(p==3) printf("%d\n",Min(0,n,1));else
		if(p==4) printf("%d\n",Max(0,n,1));else
		if(p==7)
		{
			read(x);
			printf("%d\n",find(0,n,x,1));
		} else
		if(p==5)
		{
			read(x);
			printf("%d\n",pre(0,n,x-1,1));
		} else
		{
			read(x);
			printf("%d\n",last(0,n,x+1,1));
		}
	}
	return 0;
}

  

时间: 2024-10-29 09:30:44

bzoj 3685: 普通van Emde Boas树的相关文章

BZOJ 3685: 普通van Emde Boas树( 线段树 )

建颗权值线段树就行了...连离散化都不用... 没加读入优化就TLE, 加了就A掉了...而且还快了接近1/4.... ------------------------------------------------------------------------------------------ #include<bits/stdc++.h> #define rep(i, n) for(int i = 0; i < n; i++) #define clr(x, c) memset(x

BZOJ 3685 普通van Emde Boas树 ZKW线段树

题目大意:维护一种数据结构,支持以下操作: 1 x  若x不存在,插入x 2 x  若x存在,删除x 3    输出当前最小值,若不存在输出-1 4    输出当前最大值,若不存在输出-1 5 x  输出x的前驱,若不存在输出-1 6 x  输出x的后继,若不存在输出-1 7 x  若x存在,输出1,否则输出-1 这题卡Treap,要写线段树 ZKW大法好啊 可惜我这个沙茶又写挂了-- #include<cstdio> #include<cstring> #include<i

bzoj3685普通van Emde Boas树 线段树

3685: 普通van Emde Boas树 Time Limit: 9 Sec  Memory Limit: 128 MBSubmit: 1932  Solved: 626[Submit][Status][Discuss] Description 设计数据结构支持:1 x  若x不存在,插入x2 x  若x存在,删除x3    输出当前最小值,若不存在输出-14    输出当前最大值,若不存在输出-15 x  输出x的前驱,若不存在输出-16 x  输出x的后继,若不存在输出-17 x  若x

【bzoj3685】普通van Emde Boas树 权值zkw线段树

原文地址:http://www.cnblogs.com/GXZlegend/p/6809743.html 题目描述 设计数据结构支持:1 x  若x不存在,插入x2 x  若x存在,删除x3    输出当前最小值,若不存在输出-14    输出当前最大值,若不存在输出-15 x  输出x的前驱,若不存在输出-16 x  输出x的后继,若不存在输出-17 x  若x存在,输出1,否则输出-1 输入 第一行给出n,m 表示出现数的范围和操作个数接下来m行给出操作n<=10^6,m<=2*10^6,

[CLRS][CH 20] van Emde Boas 树

vEB树简介 当关键字是有界范围内整数时,能够避免排序的 Ω(nlgn) 的下界限制.vEB树支持动态集合上运行时间为 O(lglgn) 的操作:Search, Insert, Delete, Min, Max, Successor 和 Predecessor. 接下来,用 n 表示集合中当前元素的个数,用 u 表示元素的可能取值范围.这样vEB树的操作运行时间就为 O(lglgu). 太难了...放弃先......

【权值分块】bzoj3685 普通van Emde Boas树

权值分块,虽然渐进复杂度不忍直视,但其极小的常数使得实际运行起来比平衡树快,大多数情况和递归版权值线段树差不多,有时甚至更快.但是被zkw线段树完虐. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 using namespace std; 5 #define N 1000001 6 int maxv,minv=2147483647; 7 int n,op,a,m,ma[N],en,l[1100]

BZOJ_3685_普通van Emde Boas树_权值线段树

Description 设计数据结构支持: 1 x  若x不存在,插入x 2 x  若x存在,删除x 3    输出当前最小值,若不存在输出-1 4    输出当前最大值,若不存在输出-1 5 x  输出x的前驱,若不存在输出-1 6 x  输出x的后继,若不存在输出-1 7 x  若x存在,输出1,否则输出-1 Input 第一行给出n,m 表示出现数的范围和操作个数 接下来m行给出操作 n<=10^6,m<=2*10^6,0<=x<n Output Sample Input 1

bzoj3685: 普通van Emde Boas树 set+读入优化

显然这题的所有操作都可以用set,但是直接用set肯定要T,考虑到读入量较大,使用fread读入优化,就可以卡过去了. #include<bits/stdc++.h> using namespace std; void read(int& x){ const int k=1600000; static char v, u[k],*s=u,*t=u; x=0; while(isspace(v=s==t &&u==(t=u+fread(s=u, 1,k,stdin))?-1

Van Emde Boas Tree

van Emde Boas trees 支持所有优先级优先级队列的操作,并且巧妙的是它对于SEARCH, INSERT,DELETE,MINIMUM,MAXMUN,SUCCESSOR,和PREDECESSOR这些操作的支持都在最坏复 杂度O(lglgn)之内.不过有些限制的是,所有的Kye值都必须在 0-n?1之间,且不能有重复值.换言之,他的算法复杂度不由数据的规模 有多 大而决定,而由key值的取值范围而决定. 算导上这一章的讲述方式我非常喜欢,循序渐进,从最基础最简单的一个结构开始,最终