说在前面:“CDQZ”系列题目数据绝对良心(良苦用心233),提交网址如有需要请私信本蒟蒻。
1008:Challenge 8
查看 提交 统计 提问
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 262144kB
描述
给一个长为N的数列,有M次操作,每次操作是以下三种之一:
(1)插入一个数,若已存在则忽略
(2)删除一个数,若不存在则忽略
(3)求数列中任意两数之差绝对值的最小值
输入
第一行两个正整数N和M。
第二行N的整数表示这个数列。注意若有重复的数,则视作一个。
接下来M行,每行开头是一个字符,若该字符为’I’,则表示一个插入操作,接下来一个整数x,表示插入一个数x;若该字符为’D’,则表示一个删除操作,接下来一个整数x,表示删除一个数x;若该字符为’Q’,则表示一个询问操作,求数列中任意两数之差绝对值的最小值,若不存在至少两个数,输出-1。
输出
对每一个询问操作单独输出一行,表示答案。
样例输入
5 3
1 9 3 7 5
Q
I 2
Q
样例输出
2
1
提示
1<=N<=10^5,1<=M<=10^5,输入保证合法,且所有整数可用带符号32位整型存储。
题解:treap/splay+堆,每往treap加入一个数,堆中加入两个元素:当前数-前驱、后继-当前数,删除一个元素:后继-前驱;删除就反过来。堆用优先队列实现,删除无法直接弹出可以用map打标记,在询问时判断就行。
注意:凡是要在原数列后插入新元素的,数组一定要多开,否则一个上午就没了orz
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1e5+2;
int n,m,tim,root;
int pre,suc;
priority_queue<int,vector<int>,greater<int> > q;
map<int ,int > d;
inline int read() {
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
struct DATA {
int l,r,v,rnd;
inline DATA() {l=r=0;}
}node[maxn<<1];
inline void rturn(int &k) {
int t=node[k].l;
node[k].l=node[t].r;
node[t].r=k;
k=t;
}
inline void lturn(int &k) {
int t=node[k].r;
node[k].r=node[t].l;
node[t].l=k;
k=t;
}
bool Insert(int &k,int x) {
if (k==0) {
k=++tim;
node[k].v=x,node[k].rnd=rand();
return true;
}
if (x==node[k].v) return false;
else if (x>node[k].v) {
int t=Insert(node[k].r,x);
if (node[node[k].r].rndreturn t;
}
else {
int t=Insert(node[k].l,x);
if (node[node[k].l].rndreturn t;
}
}
bool del(int &k,int x) {
if (k==0) return false;
if (x==node[k].v) {
bool j=true;
if (!node[k].l||!node[k].r) k=node[k].l+node[k].r;
else if (node[node[k].l].rndelse lturn(k),j=del(k,x);
return j;
}
else if (x>node[k].v) return del(node[k].r,x);
else return del(node[k].l,x);
}
inline void pro(int k,int x) {
while (k) {
if (node[k].velse k=node[k].l;
}
}
inline void sub(int k,int x) {
while (k) {
if (node[k].v>x) suc=k,k=node[k].l;
else k=node[k].r;
}
}
inline void update1(int val) {
pre=0,suc=0;
pro(root,val),sub(root,val);
if (pre) q.push(val-node[pre].v);
if (suc) q.push(node[suc].v-val);
if (pre&&suc) ++d[node[suc].v-node[pre].v];
}
inline void update2(int val) {
pre=0,suc=0;
pro(root,val),sub(root,val);
if (pre) ++d[val-node[pre].v];
if (suc) ++d[node[suc].v-val];
if (pre&&suc) q.push(node[suc].v-node[pre].v);
}
inline void mt() {
while (1) {
if (q.empty()) {puts("-1");return ;}
int t=q.top();
if (d[t])
while (d[t]) q.pop(),--d[t];//delete
if (q.empty()) {puts("-1");return ;}
if (t==q.top()) {printf("%d\n",t);return ;}
}
}
int main() {
// freopen("C8.in","r",stdin);
n=read(),m=read();
tim=0,root=0,d.clear();
for (register int i=1;i<=n;++i) {
int val=read();
bool j=Insert(root,val);
if (j) update1(val);
}
for (register int i=1;i<=m;++i) {
char ss;
while (!isalpha(ss=getchar()));
if (ss=='I') {
int val=read();
bool j=Insert(root,val);
if (j) update1(val);
}
else if (ss=='D') {
int val=read();
bool j=del(root,val);
if (j) update2(val);
}
else mt();
}
return 0;
}