CDQZ Challenge 8

说在前面:“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<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<climits>
#include<queue>
#include<map>
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].rnd<node[k].rnd) lturn(k);
        return t;
    }
    else {
        int t=Insert(node[k].l,x);
        if (node[node[k].l].rnd<node[k].rnd) rturn(k);
        return 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].rnd<node[node[k].r].rnd) rturn(k),j=del(k,x);
        else 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].v<x) pre=k,k=node[k].r;
        else 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值