H.Happy Triangle
思路:考虑构成三角形的充要条件是:任意两边之和大于第三边。
我们分三种情况进行讨论:
1.x是最大边
2.x是第二大边
3.x是第三大边
显然1,2两种情况可以用multiset来模拟讨论讨论。
我们用线段树来实现第三种情况的讨论,具体细节:
先将所有值存下来先离散化一下。
我们知道如果存在>=x且出现至少两次的y,则必然有解。可以用一个bit来解决这类情况。
否则,我们只需要在第一次添加和最后一次删除一个y的时候在线段树上更新大小相邻的两个点的差值。添加和删除都是最多影响两个位置的值,在multiset上二分找一下相邻的值即可。
具体实现见代码:
有问题可以私信博主QAQ
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
int n,c[N],s[N],t[N];
multiset<int>G;
int gao1(int x){
auto y=G.upper_bound(x);
if(y==G.begin())return 0;
y--;
int dx=*y;
if(y==G.begin())return 0;
y--;
return c[dx]+c[*y] >c[x];
}
int cnt[N];
int gao2(int x){
if(cnt[x]>=2)return 1;
if(cnt[x]==1){
auto y=G.upper_bound(x);
if(y!=G.end() && 2*c[x] >c[*y])return 1;
y=G.lower_bound(x);
if(y!=G.begin())return 1 ;
return 0;
}
auto y=G.upper_bound(x);
if(y==G.end())return 0;
int dx=*y;
y=G.lower_bound(x);
if(y==G.begin())return 0;
y--;
return c[dx]<c[x]+c[*y];
}
int bt[N];
void add(int x,int y){
for(;x<N;x+=x&-x)bt[x]+=y;
}
int get(int x){
int y=0;
for(;x;x-=x&-x)y+=bt[x];
return y;
}
int tr[N<<2];
#define mid (l+r>>1)
#define ls o<<1
#define rs o<<1|1
void build(int o,int l,int r){
tr[o]=2e9;
if(l==r){
return;
}
build(ls,l,mid);
build(rs,mid+1,r);
}
void up(int o,int l,int r,int x,int y){
if(l==r){
tr[o]=y;
return ;
}
if(x<=mid)up(ls,l,mid,x,y);
else up(rs,mid+1,r,x,y);
tr[o]=min(tr[ls],tr[rs]);
}
int get(int o,int l,int r,int x,int y){
if(l>=x&&r<=y){
return tr[o];
}
int ans=1e9;
if(x<=mid)ans=min(ans,get(ls,l,mid,x,y));
if(y>mid)ans=min(ans,get(rs,mid+1,r,x,y));
return ans;
}
int len;
int gao3(int x){
if(get(N-1)-get(x-1))return 1;
if(c[x]>get(1,1,len,x,len))return 1;
return 0;
}
int main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i]>>t[i];
c[i]=t[i];
}
sort(c+1,c+1+n);
len=unique(c+1,c+1+n)-c-1;
for(int i=1;i<=n;i++)t[i]=lower_bound(c+1,c+1+len,t[i])-c;
build(1,1,len);
for(int i=1;i<=n;i++){
if(s[i]==1) {
G.insert(t[i]), cnt[t[i]]++;
if(cnt[t[i]]==1){
auto y=G.upper_bound(t[i]);
if(y!=G.end()){
assert(c[*y]>c[t[i]]);
up(1,1,len,t[i],c[*y]-c[t[i]]);
}else{
up(1,1,len,t[i],2e9);
}
y--;
if(y!=G.begin()){
y--;
assert(*y<t[i]);
up(1,1,len,*y,c[t[i]]-c[*y]);
}
}
if(cnt[t[i]]==2)add(t[i],1);
}
else if(s[i]==2) {
G.erase(G.find(t[i])), cnt[t[i]]--;
if(cnt[t[i]]==0){
up(1,1,len,t[i],2e9);
auto y=G.lower_bound(t[i]);
int dx=*y;
int sta=0;
if(y==G.end())sta=1;
if(y!=G.begin()){
y--;
assert(sta||dx>*y);
up(1,1,len,*y,sta?2e9:(c[dx]-c[*y]));
}
}
if(cnt[t[i]]==1)add(t[i],-1);
} else{
int st=gao1(t[i])||gao2(t[i])||gao3(t[i]);
if(st)cout<<"Yes\n";
else cout<<"No\n";
}
}
return 0;
}