zoukankan      html  css  js  c++  java
  • BZOJ4653 [Noi2016]区间

    BZOJ4653 [Noi2016]区间


    题目描述

    传送门

    题目分析

    发现答案具有单调性,所以可以对所有区间排序之后再求解。发现部分数据值域比较小,所以思考这题是不是通过权值线段树出解。一个一个向线段树里添加区间一直到最大值大于(m)了为止,然后再一个一个删除一直删除到最大值小于(m),做差即可求出答案。

    维护一棵线段树,支持区间加和区间最大值即可。

    考虑值域较大的,可以离散化之后做。

    注意不需要查询,直接返回根节点就可以了。

    是代码呢

    #include <bits/stdc++.h>
    using namespace std;
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define mid ((l+r)>>1)
    const int inf=1e9+7;
    const int MAXN=5e5+7;
    int maxx[MAXN<<3],add[MAXN<<3],n,m,t,cnt;
    inline void pushup(int rt){maxx[rt]=max(maxx[ls],maxx[rs]);}
    struct point{
    	int pos,id;
    	bool operator <(const point &rhs)const{return pos<rhs.pos;}
    }p[MAXN<<1];
    struct po{
    	int len,l,r,id;
    	bool operator <(const po &rhs)const{return len<rhs.len;}
    }a[MAXN];
    inline void pushdown(int l,int r,int rt)
    {
    	if(add[rt]!=0){
    		maxx[ls]+=add[rt];maxx[rs]+=add[rt];
    		add[ls]+=add[rt];add[rs]+=add[rt];
    		add[rt]=0;
    	}
    }
    inline void update(int L,int R,int l,int r,int rt,int k)
    {
    	if(l>R||r<L) return;
    	if(L<=l&&r<=R){
    		maxx[rt]+=k;
    		add[rt]+=k;
    		return;
    	}
    	pushdown(l,r,rt);
    	if(L<=mid) update(L,R,l,mid,ls,k);
    	if(R>mid) update(L,R,mid+1,r,rs,k);
    	pushup(rt);
    	return;
    }
    inline int read()
    {
        int x=0,c=1;
        char ch=' ';
        while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
        while(ch=='-')c*=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*c;
    }
    int main()
    {
    	n=read();m=read();
    	for(int i=1;i<=n;i++){
    		int x=read(),y=read();
    		a[i]=(po){y-x,0,0,i};
    		p[++t]=(point){x,i};
    		p[++t]=(point){y,i};
    	}
    	sort(p+1,p+t+1);
    	p[0].pos=-1;
    	for(int i=1;i<=t;i++){
    		if(p[i].pos!=p[i-1].pos) cnt++;
    		if(!a[p[i].id].l) a[p[i].id].l=cnt;
    		else a[p[i].id].r=cnt;
    	}
    	sort(a+1,a+n+1);
    //	for(int i=1;i<=n;i++) cout<<a[i].l<<" "<<a[i].r<<" "<<a[i].id<<" "<<a[i].len<<endl;
    	int head=0,tail=0,ans=inf;
    	while(1){
    		while(maxx[1]<m&&tail<n){
    			tail++;
    			update(a[tail].l,a[tail].r,1,cnt,1,1);
    		}
    		if(maxx[1]<m) break;
    		while(maxx[1]>=m&&head<n){
    			head++;
    			update(a[head].l,a[head].r,1,cnt,1,-1);
    		}
    		
    		ans=min(ans,a[tail].len-a[head].len);
    	}
    	if(ans==inf) printf("-1
    ");
    	else printf("%d
    ", ans);
    }
    
  • 相关阅读:
    LeetCode 1275. 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game
    LeetCode 307. 区域和检索
    LeetCode 1271 十六进制魔术数字 Hexspeak
    秋实大哥与花 线段树模板
    AcWing 835. Trie字符串统计
    Leetcode 216. 组合总和 III
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 示例之 复杂(complex)属性(property)
    Mybatis 高级结果映射 ResultMap Association Collection
    Mybatis 高级结果映射 ResultMap Association Collection
  • 原文地址:https://www.cnblogs.com/victorique/p/10300937.html
Copyright © 2011-2022 走看看