Description
Given a multiset M S MS MS and q q q operations. M S MS MS is empty initailly, and operations are in three types, which are as follows:
Input
The first line contains an integer q ( 1 ≤ q ≤ 2 × 1 0 5 ) q~(1\leq q\leq 2\times 10^5) q (1≤q≤2×105), denoting the number of operations.
Following {q}q lines each contains two integers op, x ( o p ∈ { 1 , 2 , 3 } , 1 ≤ x ≤ 1 0 9 ) x~(op \in \{1,2,3\}, 1\leq x\leq 10^9) x (op∈{1,2,3},1≤x≤109) denoting an operation
4. if o p = 1 op=1 op=1, insert an element x x x into M S MS MS
5. if o p = 2 op=2 op=2, erase an element x x x from M S MS MS, it’s guaranteed that there is at least one x x x in M S MS MS currently
6. if o p = 3 op=3 op=3, determine whether you can choose two elements a , b a,b a,b in M S MS MS that three segments of length a , b , x a,b,x a,b,x can make a triangle
Output
For each query, print one line containing a string “Yes” if the answer is yes or “No” if the answer is no.
Examples
Input
8
1 1
3 1
1 1
3 2
3 1
1 2
2 1
3 1
Outpu
No
No
Yes
No
Solution
把操作离线,将所有的权值排序并离散化。
用线段树维护区间最值以及区间最小相邻元素差值
操作1和2对应线段树的修改
对于查询操作 x,有三种情况:
① x 作为三角形最小边:若 pos[x] ~ n 的最小差值小于 x 则为 Yes,反之为 No
② x 作为三角形第二大的边:1 ~ pos[x] 的最大元素和pos[x] ~ n 的最小元素分别为另外两条边
③ x 作为三角形最大边:1 ~ pos[x] 的最大元素和次大元素(非严格) 为另外两条边
其他细节见代码
思路来源:@佳爷
Code
#include
#define ls rt << 1
#define rs rt << 1 | 1
//pair
#define mpp(a,b) make_pair(a,b)
#define fir first
#define sec second
#define P pair
using namespace std;
typedef long long ll;
const int INF = 2e9;
const int maxn = 2e5+ 5;
int val[maxn];
int num[maxn];
struct Segtree{
int l,r;
int mx,mi;
int by;
}t[maxn << 3];
void push_up(int rt){
t[rt].mx = max(t[ls].mx,t[rs].mx);
t[rt].mi = min(t[ls].mi,t[rs].mi);
t[rt].by = min(t[ls].by,t[rs].by);
if(t[rs].mi != INF && t[ls].mx != 0) t[rt].by = min(t[rt].by, t[rs].mi - t[ls].mx);
}
void build(int rt,int l,int r){
t[rt].l = l, t[rt].r = r;
if(l == r){
t[rt].mx = 0, t[rt].mi = INF;
t[rt].by = INF;
return ;
}
int mid = (l + r) >> 1;
build(ls,l,mid);build(rs,mid+1,r);
push_up(rt);
}
void update(int rt,int pos,int k){
int l = t[rt].l, r = t[rt].r;
if(l == r){
num[pos] += k;
// debug1(pos);
t[rt].by = INF;
if(num[pos] == 0){
t[rt].mx = 0; t[rt].mi = INF;
} else {
t[rt].mx = t[rt].mi = val[pos];
if(num[pos] >= 2){
t[rt].by = 0;
}
}
return ;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(ls,pos,k);
else update(rs,pos,k);
push_up(rt);
}
int querymx(int rt,int L,int R){
if(L > R) return 0;
int l = t[rt].l, r = t[rt].r;
if(L <= l && r <= R){
return t[rt].mx;
}
int mid = (l + r) >> 1, res = 0;
if(L <= mid) res = max(res,querymx(ls,L,R));
if(R > mid) res = max(res,querymx(rs,L,R));
return res;
}
int querymi(int rt,int L,int R){
if(L > R) return INF;
int l = t[rt].l, r = t[rt].r;
if(L <= l && r <= R){
return t[rt].mi;
}
int mid = (l + r) >> 1, res = INF;
if(L <= mid) res = min(res,querymi(ls,L,R));
if(R > mid) res = min(res,querymi(rs,L,R));
return res;
}
int queryby(int rt,int L,int R,int n){
if(L > R) return INF;
int l = t[rt].l, r = t[rt].r;
if(L <= l && r <= R){
return t[rt].by;
}
int mid = (l + r) >> 1, res = INF;
int f1 = 0, f2 = 0;
if(L <= mid) {res = min(res,queryby(ls,L,R,n)); f1 = 1;}
if(R > mid) {res = min(res,queryby(rs,L,R,n)); f2 = 1;}
int pos = lower_bound(val + 1,val + 1 + n,t[ls].mx) - val;
if(f1 && f2 && t[ls].mx != 0 && t[rs].mi != INF && pos >= L) res = min(res,t[rs].mi - t[ls].mx);
return res;
}
P qu[maxn];
bool check(int n,int pos,int x){
if(num[pos] >= 2) return true;
if(num[pos] == 1){
int la = querymx(1,1,pos-1);if(la != 0 && 1ll * la + x > 1ll * x) return true;
int minby = queryby(1,pos,n,n);
if(minby < x) return true;
return false;
}
int lma = querymx(1,1,pos);
int rmi = querymi(1,pos,n);
int pos1 = lower_bound(val + 1,val + 1 + n,lma) - val;
if(lma != 0 && rmi != INF){
if(1ll * lma + 1ll * x > 1ll * rmi){
return true;
}
}
if(lma != 0){
update(1,pos1,-1);
int lma2 = querymx(1,1,pos);
update(1,pos1,1);
if(lma2 != 0 && 1ll * lma + 1ll * lma2 > 1ll * x) return true;
}
int by = queryby(1,pos,n,n);
if(by < x) return true;
return false;
}
int main(){
int q;scanf("%d",&q);
for(int i = 1;i <= q;++i){
scanf("%d %d",&qu[i].fir,&qu[i].sec);
val[i] = qu[i].sec;
}
sort(val + 1,val + 1 + q);
int n = unique(val + 1,val + 1 + q) - val - 1;
build(1,1,n);
for(int i = 1;i <= q;++i){
int pos = lower_bound(val + 1,val + 1 + n,qu[i].sec) - val;
if(qu[i].fir == 1) update(1,pos,1);
if(qu[i].fir == 2) update(1,pos,-1);
if(qu[i].fir == 3){
if(check(n,pos,qu[i].sec)) printf("Yes\n"); else printf("No\n");
}
}
return 0;
}