zoukankan      html  css  js  c++  java
  • 【BZOJ4653】[Noi2016]区间 双指针法+线段树

    【BZOJ4653】[Noi2016]区间

    Description

    在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
    对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
    求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

    Input

    第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n
     
    接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。
    N<=500000,M<=200000,0≤li≤ri≤10^9

    Output

    只有一行,包含一个正整数,即最小花费。

    Sample Input

    6 3
    3 5
    1 2
    3 4
    2 2
    1 5
    1 4

    Sample Output

    2

    题解:这不是我最喜爱的(没有之一)双指针法吗?然而GXZ没等我看题就告诉我正解简直丧心病狂~

    因为总代价只和最长区间和最短区间有关,我们将区间按长度排序,那么中间的区间都可以免费取。我们采用双指针法,枚举右端点r,再不断右移l直到[l,r]中的区间刚好满足条件。是否满足条件可以用线段树判定,只需要再每次平移指针的时候维护一下线段树就行了。

     

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=500010;
    int n,m,nm,ans;
    int s[maxn<<4],t[maxn<<4];
    struct node
    {
    	int len,a,b;
    }p[maxn];
    struct number
    {
    	int val,org,k;
    }num[maxn<<1];
    bool cmp1(node a,node b)
    {
    	return a.len<b.len;
    }
    bool cmp2(number a,number b)
    {
    	return a.val<b.val;
    }
    int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void updata(int l,int r,int x,int a,int b,int v)
    {
    	if(a<=l&&r<=b)
    	{
    		s[x]+=v,t[x]+=v;
    		return ;
    	}
    	if(t[x])	s[lson]+=t[x],s[rson]+=t[x],t[lson]+=t[x],t[rson]+=t[x],t[x]=0;
    	int mid=l+r>>1;
    	if(a<=mid)	updata(l,mid,lson,a,b,v);
    	if(b>mid)	updata(mid+1,r,rson,a,b,v);
    	s[x]=max(s[lson],s[rson]);
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i,j;
    	for(i=1;i<=n;i++)
    		num[i].val=rd(),num[i+n].val=rd(),num[i].org=num[i+n].org=i,num[i+n].k=1,p[i].len=num[i+n].val-num[i].val;
    	sort(num+1,num+2*n+1,cmp2);
    	num[i-1].val=-1;
    	for(i=1;i<=2*n;i++)
    	{
    		if(num[i].val>num[i-1].val)	nm++;
    		if(num[i].k)	p[num[i].org].b=nm;
    		else	p[num[i].org].a=nm;
    	}
    	sort(p+1,p+n+1,cmp1);
    	ans=1<<30;
    	for(i=1;i<=n&&s[1]<m;updata(1,nm,1,p[i].a,p[i].b,1),i++);
    	if(i>n&&s[1]<m)
    	{
    		printf("-1");
    		return 0;
    	}
    	i--,updata(1,nm,1,p[i].a,p[i].b,-1);
    	for(j=1;i<=n;i++)
    	{
    		for(updata(1,nm,1,p[i].a,p[i].b,1);j<=i&&s[1]>=m;updata(1,nm,1,p[j].a,p[j].b,-1),j++);
    		j--,updata(1,nm,1,p[j].a,p[j].b,1);
    		ans=min(ans,p[i].len-p[j].len);
    	}
    	printf("%d",ans);
    	return 0;
    }
    //6 3 3 5 1 2 3 4 2 2 1 5 1 4

     

  • 相关阅读:
    从零开始入门 K8s | 应用编排与管理
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    203. Remove Linked List Elements
    183. Customers Who Never Order
    182. Duplicate Emails
    181. Employees Earning More Than Their Managers
    1261. Find Elements in a Contaminated Binary Tree
    1260. Shift 2D Grid
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7130202.html
Copyright © 2011-2022 走看看