bzoj3685 普通veb树
2016-01-17 09:13
351 查看
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
常规做法是用线段树,但根据这题的特点,还有很多其它数据结构可以用。
将线段树和trie结合,可得每个结点有8个子结点的线段树,每个结点压位维护8个子树是否非空。
预处理每个状态最左/右非空子树位置。
插入或删除时自底向上修改。查询前驱后继时自底向上找到前驱或后继所在区间再向下找到其具体位置。
最后加读入/输出优化,比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
Input
第一行给出n,m 表示出现数的范围和操作个数
接下来m行给出操作
n<=10^6,m<=2*10^6,0<=x<n
常规做法是用线段树,但根据这题的特点,还有很多其它数据结构可以用。
将线段树和trie结合,可得每个结点有8个子结点的线段树,每个结点压位维护8个子树是否非空。
预处理每个状态最左/右非空子树位置。
插入或删除时自底向上修改。查询前驱后继时自底向上找到前驱或后继所在区间再向下找到其具体位置。
最后加读入/输出优化,比zkw线段树略快一点,内存也省了很多。
#include<cstdio> inline int read(){ char c=getchar(); int x=0; while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x; } char str[16]; inline void print(int x){ if(!x){ puts("0"); return; } if(x<0)putchar('-'),x=-x; int p=0; while(x)str[p++]=x%10+'0',x/=10; while(p)putchar(str[--p]); putchar(10); } bool d[2097154]; unsigned char ds[8][262144]; int lp[256],rp[256]; int ls[8],rs[8]; inline void ins(int x){ if(d[x])return; d[x]=1; for(int i=1;i<=7;i++)ds[i][x>>i*3]|=1<<((x>>i*3-3)&7); } inline void del(int x){ if(d[x])d[x]=0; else return; for(int i=1;i<=7;i++)if(ds[i][x>>i*3]^=1<<((x>>i*3-3)&7))return; } inline int minv(){ if(!ds[7][0])return -1; register int p=lp[ds[7][0]]; for(int i=6;i;--i)p=(p<<3)+lp[ds[i][p]]; return p; } inline int maxv(){ if(!ds[7][0])return -1; register int p=rp[ds[7][0]]; for(int i=6;i;--i)p=(p<<3)+rp[ds[i][p]]; return p; } inline int prv(int p){ if(!ds[7][0])return -1; register int s=ds[1][p>>3]&ls[p&7]; if(s)return (p^(p&7))|rp[s]; for(int i=2;i<=7;i++){ p>>=3; s=ds[i][p>>3]&ls[p&7]; if(s){ p=(p^(p&7))|rp[s]; for(int j=i-1;j;--j)p=(p<<3)|rp[ds[j][p]]; return p; } } return -1; } inline int nxt(int p){ if(!ds[7][0])return -1; register int s=ds[1][p>>3]&rs[p&7]; if(s)return (p^(p&7))|lp[s]; for(int i=2;i<=7;i++){ p>>=3; s=ds[i][p>>3]&rs[p&7]; if(s){ p=(p^(p&7))|lp[s]; for(int j=i-1;j;--j)p=(p<<3)|lp[ds[j][p]]; return p; } } return -1; } int n,m,a,b; int main(){ for(int i=1;i<256;i++){ int j=0; while(!(i&1<<j))++j; lp[i]=j; j=7; while(!(i&1<<j))--j; rp[i]=j; } for(int i=0;i<8;i++)ls[i]=255>>8-i,rs[i]=255&(255<<i+1); n=read(); m=read(); for(int i=0;i<m;i++){ a=read(); if(a<3){ b=read(); if(a==1)ins(b); else if(a==2)del(b); }else if(a>4){ b=read(); if(a==5)print(prv(b)); else if(a==6)print(nxt(b)); else if(a==7)puts(d[b]&&ds[1][b>>3]&1<<(b&7)?"1":"-1"); }else if(a==3)print(minv()); else if(a==4)print(maxv()); } return 0; }
相关文章推荐
- ListView上下自动滑动
- 2015年读书回顾
- 【NCL】添加中文字符
- 【NCL】确定要添加字符在页面上的位置-drawNDCGrid
- Validform+layer实现漂亮的表单验证特效
- C++ 学习笔记(一些新特性总结 1)
- 联接
- C++ 学习笔记(一些新特性总结 1)
- 【NCL】获取plot图经纬度的页面坐标-datatondc
- zend studio 10 字体,颜色,快捷键等相关设置
- day09-----------面向对象(传智视频)
- win10怎么这只让任务栏图标居中显示?
- 【NCL】复制变量的元数据(属性和坐标)-copy_VarMeta
- 解决ZendStudio打开utf-8格式的php文件乱码
- 分支语句的使用(比较大小)
- SQL高级查询
- mysql安装配置
- javascript实现倒计时跳转页面
- 【NCL】shea_util.ncl只能load一次
- 为什么使用指针比使用对象本身更好?