2020牛客暑期多校训练营(第二场)

  • H.Happy Triangle

  • 维护一个集合。集合支持三种操作。1、往集合里加入一个元素x。2、往集合里删除一个容器x。3、给定一个x,询问是否能从容器找找到y,z,使得x,y,z能组成三角形。操作数<=10^5,x<=10^9。

  • 先将所有的x离散化。然后可用权值线段树。维护权值线段树的最大值最小值,数量和区间最小差值。

  • 总共有三种可能。

  • 1、x<=y<=z 此时,我们需要找到y-z的最小差值。这就是要维护区间最小差的原因。

  • 2、y<=x<=z 此时,需要找到小于x且最大的y,大于x且最小的z,然后判断能否组成三角形。线段树上直接搜即可。

  • 3、y<=z<=x 此时,找到小于x且前2大的数,然后判断能否组成三角形。

  • #include
    #define N 205000
    #define inf 0x3f3f3f3f
    using namespace std;
    map mp;
    int a[N];
    int b[N];
    int op[N];
    int n;
    void lisan() {
    	int i,x;
    	for (i=1;i<=n;i++) b[i]=a[i];
    	sort(b+1,b+1+n);
    	for (i=1;i<=n;i++) {
    		x=lower_bound(b+1,b+1+n,a[i])-b;
    		mp[x]=a[i];
    		a[i]=x;
    	}	
    }
    struct node{
    	int left,right,interval,sum;
    }tree[N<<2];
    void pushup(int rt) {
    	tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
    	tree[rt].interval=min(tree[rt<<1].interval,tree[rt<<1|1].interval);
    	tree[rt].left=min(tree[rt<<1].left,tree[rt<<1|1].left);
    	tree[rt].right=max(tree[rt<<1].right,tree[rt<<1|1].right);
    	if (tree[rt<<1].sum>0&&tree[rt<<1|1].sum>0) 
    		tree[rt].interval=min(tree[rt].interval,mp[tree[rt<<1|1].left]-mp[tree[rt<<1].right]);
    		
    }
    void build(int l,int r,int rt){
    	if (l==r) {
    		tree[rt].left=inf;
    		tree[rt].right=0;
    		tree[rt].sum=0;
    		tree[rt].interval=inf;
    		return ;
    	}
    	int m=(l+r)>>1;
    	build(l,m,rt<<1);
    	build(m+1,r,rt<<1|1);
    	pushup(rt);
    }
    void add(int l,int r,int x,int s,int rt) {
    	if (l==r) {
    		tree[rt].sum+=s;
    		if (tree[rt].sum>0) {
    			tree[rt].left=x;
    			tree[rt].right=x;
    		} else {
    			tree[rt].left=inf;
    			tree[rt].right=0;
    		}
    		if (tree[rt].sum>1) tree[rt].interval=0;
    			else tree[rt].interval=inf;
    		return;
    	}
    	int m=(l+r)>>1;
    	if (x<=m) add(l,m,x,s,rt<<1);
    	else add(m+1,r,x,s,rt<<1|1);
    	pushup(rt);
    	
    }
    int query_max(int l,int r,int x,int rt) {
    	if (tree[rt].sum==0) {
    		return -1;
    	}
    	if (l==r) {
    		return tree[rt].left;
    	}
    	int m=(l+r)>>1;
    	if (x<=m) return query_max(l,m,x,rt<<1);
    	else return max(tree[rt<<1].right,query_max(m+1,r,x,rt<<1|1));
    }
    int query_min(int l,int r,int x,int rt) {
    	if (tree[rt].sum==0) {
    		return inf;
    	}
    	if (l==r) {
    		return tree[rt].left;
    	}
    	int m=(l+r)>>1;
    	if (x>m) return query_min(m+1,r,x,rt<<1|1);
    	else return min(tree[rt<<1|1].left,query_min(l,m,x,rt<<1));
    }
    
    node query_int(int l,int r,int x,int rt) {
    	node tmp,re;
    	if (tree[rt].sum==0) {
    		return tree[rt];
    	}
    	if (l==r) {
    		return tree[rt];
    	}
    	int m=(l+r)>>1;
    	if (x>m) return query_int(m+1,r,x,rt<<1|1);
    	else { 
    		tmp=query_int(l,m,x,rt<<1);
    		re.sum=tmp.sum+tree[rt<<1|1].sum;
    		re.interval=min(tmp.interval,tree[rt<<1|1].interval);
    		re.left=min(tmp.left,tree[rt<<1|1].left);
    		re.right=max(tmp.right,tree[rt<<1|1].right);
    		if (tmp.sum>0&&tree[rt<<1|1].sum>0) 
    		re.interval=min(re.interval,mp[tree[rt<<1|1].left]-mp[tmp.right]);
    		return re;
    	}
    }
    
    int main(){
    	int e,t,x,y;
    	node p;
    	int i;
    	scanf("%d",&n);
    	for (i=1;i<=n;i++) scanf("%d %d",&op[i],&a[i]);
    	lisan();
    	build(1,n,1);
    	for (i=1;i<=n;i++) {
    		if (op[i]==1) {
    			add(1,n,a[i],1,1);
    		}
    		if (op[i]==2) {
    			add(1,n,a[i],-1,1);
    		}
    		if (op[i]==3) {
    			//x<=a[i]<=y
    			x=query_max(1,n,a[i],1); // max<=a[i]
    			add(1,n,x,-1,1);
    			y=query_min(1,n,a[i],1);
    			add(1,n,x,1,1);
    			if (x!=-1&&y!=inf) if (mp[x]+mp[a[i]]>mp[y]) {printf("Yes
    ");continue;}
    			y=query_min(1,n,a[i],1);// max<=a[i]
    			add(1,n,y,-1,1);
    			x=query_max(1,n,a[i],1); 
    			add(1,n,y,1,1);
    			if (x!=-1&&y!=inf) if (mp[x]+mp[a[i]]>mp[y]) {printf("Yes
    ");continue;}
    			//a[i]<=x<=y
    			p=query_int(1,n,a[i],1);
    			x=p.interval;
    			if (x!=inf) if (mp[a[i]]>x) {printf("Yes
    ");continue;}
    			//x<=y<=a[i]
    			x=query_max(1,n,a[i],1);
    			add(1,n,x,-1,1);
    			y=query_max(1,n,a[i],1);
    			add(1,n,x,1,1);
    			if (x!=-1&&y!=-1)
    			if (mp[x]+mp[y]>mp[a[i]]) {printf("Yes
    ");continue;}
    			printf("No
    ");
    		}
    	}
    }
    
    
原文地址:https://www.cnblogs.com/nowheretrix/p/13326393.html