1. 程式人生 > 實用技巧 >H Happy Triangle(詢問是否構成三角形)

H Happy Triangle(詢問是否構成三角形)

題:https://ac.nowcoder.com/acm/contest/5667/H

題意:給定空的容器multiset:MS,有q個操作,操作一為向MS中加入x,操作二為在MS刪除x,操作三為詢問在MS是否存在a,b與x能形成一個不退化的三角形。

分析:對於詢問操作,有倆種情況,情況一是x作為最大邊,這種情況只要判斷在MS中小於等於x的最大的倆個數來判斷能否形成三角形,用一個set容器即可搞定;

   情況二為x不作為最大邊,假設有a<=b滿足條件,因為這種情況b肯定比x大,而a在越接近於b的情況下,x,a,b更容易滿足條件,轉化為b-a越小越能滿足條件,所以這中情況,只要找x字尾中與前驅a之差最小的值ans,若ans<x說明存在,否則不存在,這部分可以用線段樹解決。

   而操作一和操作二根據線段樹值的確立來進行相應的操作即可。

   (記得開ll)

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int mod=1e9+7;
const int M=2e5+5;
const ll inf=1e18;
ll tr[M<<2
],lisan[M],cnt[M],a[M],op[M],m; multiset<ll>MS; void pn(){ puts("No"); } void py(){ puts("Yes"); } void up(int root){ tr[root]=min(tr[root<<1],tr[root<<1|1]); } void build(int root,int l,int r){ tr[root]=inf; ///cout<<l<<" "<<r<<endl; if(l==r)
return ; int midd=(l+r)>>1; build(lson); build(rson); } void update(int pos,ll c,int root,int l,int r){ if(l==r){ tr[root]=c; return ; } int midd=(l+r)>>1; if(pos<=midd) update(pos,c,lson); else update(pos,c,rson); up(root); } ll query(int L,int R,int root,int l,int r){ if(L<=l&&r<=R) return tr[root]; int midd=(l+r)>>1; ll minn=inf; if(L<=midd) minn=min(minn,query(L,R,lson)); if(R>midd) minn=min(minn,query(L,R,rson)); return minn; } void solve1(int x){ int pos=lower_bound(lisan+1,lisan+1+m,x)-lisan; if(cnt[pos]){ update(pos,0,1,1,m); } else{ auto it=MS.lower_bound(x); auto tmp=it; ///更新當前插入位 it--; update(pos,x-*it,1,1,m); ///更新當前插入位的後一位 int pos2=lower_bound(lisan+1,lisan+1+m,*tmp)-lisan; if(cnt[pos2]<2) update(pos2,*tmp-x,1,1,m); } cnt[pos]++; MS.insert(x); } void solve2(int x){ int pos=lower_bound(lisan+1,lisan+1+m,x)-lisan; if(cnt[pos]==2){ auto it=MS.lower_bound(x); it--; update(pos,x-*it,1,1,m); } else if(cnt[pos]==1){ update(pos,inf,1,1,m); auto pre=MS.lower_bound(x);pre--; auto las=MS.upper_bound(x); int pos2=lower_bound(lisan+1,lisan+1+m,*las)-lisan; if(cnt[pos2]<2){ update(pos2,*las-*pre,1,1,m); } } cnt[pos]--; ///因為只刪一個,所以不能直接刪除 auto it=MS.lower_bound(x); MS.erase(it); } void solve3(int x){ ///x作為最大邊 auto it=MS.upper_bound(x);it--; if(it!=MS.begin()){ auto tmp=it;it--; if(*tmp+*it>x){ py(); return ; } } ///x不作為最大邊 it=MS.upper_bound(x); int pos=lower_bound(lisan+1,lisan+1+m,*it)-lisan; if(query(pos,m,1,1,m)<x) py(); else pn(); return ; } int main(){ int n,tot=0; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&op[i],&a[i]); lisan[++tot]=a[i]; } lisan[++tot]=inf,lisan[++tot]=-inf; sort(lisan+1,lisan+1+tot); m=unique(lisan+1,lisan+1+tot)-lisan-1; MS.insert(inf),MS.insert(-inf); build(1,1,m); for(int i=1;i<=n;i++){ if(op[i]==1)solve1(a[i]); else if(op[i]==2)solve2(a[i]); else solve3(a[i]); } return 0; }
View Code