zoukankan      html  css  js  c++  java
  • 【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;
    }
    
  • 相关阅读:
    台州 OJ 3847 Mowing the Lawn 线性DP 单调队列
    洛谷 OJ P1417 烹调方案 01背包
    快速幂取模
    台州 OJ 2649 More is better 并查集
    UVa 1640
    UVa 11971
    UVa 10900
    UVa 11346
    UVa 10288
    UVa 1639
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513395.html
Copyright © 2011-2022 走看看