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
题解
感觉大家都是用线段树写的qwq我好想不会啊。
窝认为treap也能写啊。
我维护了一个treap和一些数组:
vis[i]表示i是否存在
pre[i]表示i的前驱(若i存在)
next[i]表示i的后继(若i存在)
1、2、5、6都是O(log n)
3、4、7是O(1)
然后大家自己看代码我是怎么维护的。。。(脑补吧)
吐槽:加个读入优化快了2000ms。。。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct node{
node *ch[2];
int v,r;
node(int x){ch[0] = ch[1] = NULL;r = rand();v = x;}
int cmp(int x)
{
if(v == x) return -1;
else return v > x ? 0 : 1;
}
}*root;
#define N 1000010
bool vis[N];
int pre[N],next[N];
int n,m;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void rotate(node* &o,int d)
{
node *k = o->ch[d^1];
o->ch[d^1] = k->ch[d];
k->ch[d] = o;
o = k;
}
void insert(node* &o,int x)
{
if(o == NULL) o = new node(x);
else
{
int d = o->cmp(x);
if(d == 0) next[x] = o->v; else pre[x] = o->v;
insert(o->ch[d],x);
if(o->ch[d]->r > o->r) rotate(o,d^1);
}
}
void remove(node* &o,int x)
{
int d = o->cmp(x);
if(d == -1)
{
node* u = o;
if(o->ch[0] && o->ch[1])
{
int d2 = o->ch[0]->r > o->ch[1]->r ? 1 : 0;
rotate(o,d2);remove(o->ch[d2],x);
}
else
{
if(o->ch[0]) o = o->ch[0]; else o = o->ch[1];
delete u;
}
}
else remove(o->ch[d],x);
}
int ans;
void ask_before(node* o,int x)
{
if(o == NULL) return;
if(o->v < x)
{
ans = o->v;
ask_before(o->ch[1],x);
}else ask_before(o->ch[0],x);
}
void ask_after(node* o,int x)
{
if(o == NULL) return;
if(o->v > x)
{
ans = o->v;
ask_after(o->ch[0],x);
}else ask_after(o->ch[1],x);
}
int main()
{
int opt,x,minn = -1,maxn = -1;
n=read(); m=read();
memset(vis,false,sizeof(vis));
while(m--)
{
opt = read();
if(opt != 3 && opt != 4) x = read();
if(opt == 1)
if(!vis[x])
{
pre[x] = next[x] = -1; vis[x] = 1;
insert(root,x);
if(pre[x] == -1) minn = x; else next[pre[x]] = x;
if(next[x] == -1) maxn = x; else pre[next[x]] = x;
}
if(opt == 2)
if(vis[x])
{
if(x == minn) minn = next[x];
if(x == maxn) maxn = pre[x];
remove(root,x);
if(pre[x] != -1) next[pre[x]] = next[x];
if(next[x] != -1) pre[next[x]] = pre[x];
vis[x] = 0;
}
if(opt == 3) printf("%d\n",minn);
if(opt == 4) printf("%d\n",maxn);
if(opt == 5) { ans = -1; ask_before(root,x); printf("%d\n",ans); }
if(opt == 6) { ans = -1; ask_after(root,x); printf("%d\n",ans); }
if(opt == 7) printf("%d\n",vis[x] ? 1 : -1);
}
return 0;
}