• 【BZOJ4653】【NOI2016】区间 线段树


    题目大意

      数轴上有(n)个闭区间([l_1,r_1],[l_2,r_2],ldots,[l_n,r_n]),你要选出(m)个区间,使得存在一个(x),对于每个选出的区间([l_i,r_i])都有(xin[l_i,r_i])

      一个方案的代价是最长区间长度减去最短区间长度。

      求最小的代价。

      无解输出(-1)

      (mleq nleq 500000)

    题解

      就是选出(m)个区间,包含同一个点。

      如果多选一些区间,那么答案不会变小。

      问题转化成选一些区间,使得存在一个点被(m)个区间包含。

      把这些区间按长度排序,用线段树维护每个点被包含的次数。

      枚举左端点和右端点,查询是否有一个点被包含(m)次。

      设(f_i)为选第(i)个区间为最长的区间时最短的区间是哪个。

      显然(f_i)是单调递增的

      直接用两个指针维护就行了

      因为区间端点的范围很大,所以要离散化。

      时间复杂度:(O(nlog n))

    题解

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<cmath>
    #include<functional>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> pll;
    void sort(int &a,int &b)
    {
    	if(a>b)
    		swap(a,b);
    }
    void open(const char *s)
    {
    #ifndef ONLINE_JUDGE
    	char str[100];
    	sprintf(str,"%s.in",s);
    	freopen(str,"r",stdin);
    	sprintf(str,"%s.out",s);
    	freopen(str,"w",stdout);
    #endif
    }
    int rd()
    {
    	int s=0,c;
    	while((c=getchar())<'0'||c>'9');
    	do
    	{
    		s=s*10+c-'0';
    	}
    	while((c=getchar())>='0'&&c<='9');
    	return s;
    }
    int upmin(int &a,int b)
    {
    	if(b<a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    int upmax(int &a,int b)
    {
    	if(b>a)
    	{
    		a=b;
    		return 1;
    	}
    	return 0;
    }
    struct section
    {
    	int l,r;
    	int d;
    };
    int cmp(section a,section b)
    {
    	return a.d<b.d;
    }
    namespace seg
    {
    	struct node
    	{
    		int l,r,ls,rs,s,t;
    	};
    	node a[2000010];
    	int n;
    	void build(int &p,int l,int r)
    	{
    		p=++n;
    		a[p].l=l;
    		a[p].r=r;
    		if(l==r)
    			return;
    		int mid=(l+r)>>1;
    		build(a[p].ls,l,mid);
    		build(a[p].rs,mid+1,r);
    	}
    	void add(int p,int v)
    	{
    		a[p].s+=v;
    		a[p].t+=v;
    	}
    	void push(int p)
    	{
    		if(a[p].l!=a[p].r&&a[p].t)
    		{
    			add(a[p].ls,a[p].t);
    			add(a[p].rs,a[p].t);
    			a[p].t=0;
    		}
    	}
    	void add(int p,int l,int r,int v)
    	{
    		if(l<=a[p].l&&r>=a[p].r)
    		{
    			add(p,v);
    			return;
    		}
    		int mid=(a[p].l+a[p].r)>>1;
    		push(p);
    		if(l<=mid)
    			add(a[p].ls,l,r,v);
    		if(r>mid)
    			add(a[p].rs,l,r,v);
    		a[p].s=max(a[a[p].ls].s,a[a[p].rs].s);
    	}
    	int query(int p,int l,int r)
    	{
    		if(l>r)
    			return 0;
    		if(l<=a[p].l&&r>=a[p].r)
    			return a[p].s;
    		push(p);
    		int mid=(a[p].l+a[p].r)>>1;
    		int res=0;
    		if(l<=mid)
    			upmax(res,query(a[p].ls,l,r));
    		if(r>mid)
    			upmax(res,query(a[p].rs,l,r));
    		return res;
    	}
    }
    using seg::build;
    using seg::add;
    using seg::query;
    section a[500010];
    int d[1000010];
    int main()
    {
    //	open("bzoj4653");
    	int n,m;
    	scanf("%d%d",&n,&m);
    	int i;
    	int t=0;
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d%d",&a[i].l,&a[i].r);
    		a[i].d=a[i].r-a[i].l+1;
    		d[++t]=a[i].l;
    		d[++t]=a[i].r;
    	}
    	sort(d+1,d+t+1);
    	t=unique(d+1,d+t+1)-d-1;
    	sort(a+1,a+n+1,cmp);
    	for(i=1;i<=n;i++)
    	{
    		a[i].l=lower_bound(d+1,d+t+1,a[i].l)-d;
    		a[i].r=lower_bound(d+1,d+t+1,a[i].r)-d;
    	}
    	int j=1;
    	int rt;
    	build(rt,1,t);
    	int ans=0x7fffffff;
    	for(i=1;i<=n;i++)
    	{
    		add(rt,a[i].l,a[i].r,1);
    		while(max(query(rt,a[j].l,a[j].r)-1,max(query(rt,1,a[j].l-1),query(rt,a[j].r+1,t)))>=m)
    		{
    			add(rt,a[j].l,a[j].r,-1);
    			j++;
    		}
    		if(query(rt,1,t)>=m)
    			ans=min(ans,a[i].d-a[j].d);
    	}
    	if(ans==0x7fffffff)
    		ans=-1;
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    设置标题自适应宽度,动态调整大小
    终止延迟函数
    iOS 关于音频开发
    阻止iOS设备锁屏
    苹果开发——设置iTunes Connect中的Contracts, Tax, and Banking
    【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取"产品付费数量等于0的问题"】
    uibutton 设置title 居左显示
    通过view 获取viewController
    tableview 自动滑动到某一行
    uibutton 设置圆角边框
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513395.html
Copyright © 2020-2023  润新知