考虑以下情况:
- 当x为最大值时:找到两个前驱 p1、p2,存在 p1 + p2 > x 即合法。
- 当x为不是最大值时:
- 找到两个前驱 p1、p2,存在 p1 + p2 > x 即合法。
- 找到一个值 p1 >= x,p2 为 p1 的前驱,存在 p1 - p2 < x 即合法。
离散化后set,cnt数组共同维护pre,nxt,线段树维护相邻两个数之差。
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, ll> pii;
typedef vector<int> vi;
const int maxn = 4e5 + 10, mod = 1e9 + 7;
const ll inf = 1e18;
pii a[maxn];
int tot, n, cnt[maxn];
ll ls[maxn];
struct Tree
{
int l, r;
ll mn, lm, rm;
}tree[maxn << 2];
void push_up(int p) {tree[p].mn = min(tree[p<<1].mn, tree[p<<1|1].mn);}
void build(int p, int l, int r)
{
tree[p].l = l;
tree[p].r = r;
tree[p].lm = tree[p].rm = tree[p].mn = inf;
if(l == r) return;
int mid = l + r >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
push_up(p);
}
ll query(int p, int l, int r)
{
if(l <= tree[p].l and tree[p].r <= r)
return tree[p].mn;
int mid = tree[p].l + tree[p].r >> 1;
ll mn = inf;
if(l <= mid)
mn = min(mn, query(p<<1, l, r));
if(r > mid)
mn = min(mn, query(p<<1|1, l, r));
return mn;
}
void change(int p, int x, ll lm, ll rm)
{
if(tree[p].l == tree[p].r)
{
if(lm != -1) tree[p].lm = lm;
if(rm != -1) tree[p].rm = rm;
tree[p].mn = min(tree[p].lm, tree[p].rm);
return;
}
int mid = tree[p].l + tree[p].r >> 1;
if(x <= mid)
change(p<<1, x, lm, rm);
else
change(p<<1|1, x,lm, rm);
push_up(p);
}
set<int> st;
void add(ll x)
{
int v = lower_bound(ls+1, ls+1+tot, x) - ls;
if(!cnt[v])
{
auto pre = --st.lower_bound(v);
auto nxt = st.upper_bound(v);
change(1, v, ls[v] - ls[*pre], ls[*nxt] - ls[v]);
if(cnt[*pre] == 1)
change(1, *pre, -1, ls[v] - ls[*pre]);
if(cnt[*nxt] == 1)
change(1, *nxt, ls[*nxt] - ls[v], -1);
cnt[v]++;
st.insert(v);
}else
{
cnt[v]++;
change(1, v, 0, 0);
}
}
void del(ll x)
{
int v = lower_bound(ls+1, ls+1+tot, x) - ls;
if(cnt[v] >= 3)
{
cnt[v]--;
}else if(cnt[v] == 2)
{
auto pre = --st.lower_bound(v);
auto nxt = st.upper_bound(v);
change(1, v, ls[v] - ls[*pre], ls[*nxt] - ls[v]);
cnt[v]--;
}else if(cnt[v] == 1)
{
auto pre = --st.lower_bound(v);
auto nxt = st.upper_bound(v);
change(1, v, inf, inf);
if(cnt[*pre] < 2)
change(1, *pre, -1, ls[*nxt] - ls[*pre]);
if(cnt[*nxt] < 2)
change(1, *nxt, ls[*nxt] - ls[*pre], -1);
st.erase(v);
cnt[v]--;
}
}
bool ask(ll x)
{
int v = lower_bound(ls+1, ls+1+tot, x) - ls;
auto nxt = st.upper_bound(v);
if(st.size() == 2) return false;
if(*nxt == tot)
{
int a = *(--nxt);
int b = 1;
if(cnt[*nxt] >= 2) b = a;
else if(nxt != st.begin()) b = *(--nxt);
return ls[a] + ls[b] > x;
}else
{
int a = *(--nxt);
int b = 1;
if(cnt[*nxt] >= 2) b = a;
else if(nxt != st.begin()) b = *(--nxt);
if(ls[a] + ls[b] > x) return true;
return query(1, v, tot) < x;
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i].first >> a[i].second;
ls[i] = a[i].second; //离散化
}
ls[n+1] = -inf; // 哨兵
ls[n+2] = inf;
sort(ls+1, ls+3+n);
tot = unique(ls+1, ls+3+n) - ls - 1;
st.insert(1);
cnt[1] = 1;
st.insert(tot);
cnt[tot] = 1;
build(1, 1, tot);
for(int i = 1; i <= n; i++)
{
int op = a[i].first, x = a[i].second;
if(op == 1)
add(x);
else if(op == 2)
del(x);
else cout << (ask(x)? "Yes": "No") << '\n';
}
return 0;
}