首页 > 代码库 > 百度之星2017 HDU 6119 小小粉丝度度熊 二分+双指针

百度之星2017 HDU 6119 小小粉丝度度熊 二分+双指针

小小粉丝度度熊

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6119

Description

度度熊喜欢着喵哈哈村的大明星——星星小姐。
为什么度度熊会喜欢星星小姐呢?
首先星星小姐笑起来非常动人,其次星星小姐唱歌也非常好听。
但这都不是最重要的,最重要的是,星星小姐拍的一手好代码!
于是度度熊关注了星星小姐的贴吧。
一开始度度熊决定每天都在星星小姐的贴吧里面签到。
但是度度熊是一个非常健忘的孩子,总有那么几天,度度熊忘记签到,于是就断掉了他的连续签到。
不过度度熊并不是非常悲伤,因为他有m张补签卡,每一张补签卡可以使得某一忘签到的天,变成签到的状态。
那么问题来了,在使用最多m张补签卡的情况下,度度熊最多连续签到多少天呢?

Input

本题包含若干组测试数据。
第一行两个整数n,m,表示有n个区间,这n个区间内的天数,度度熊都签到了;m表示m张补签卡。
接下来n行,每行两个整数(l[i],r[i]),表示度度熊从第l[i]天到第r[i]天,都进行了签到操作。
数据范围:
1<=n<=100000
0<=m<=1000000000
0<=l[i]<=r[i]<=1000000000
注意,区间可能存在交叉的情况。

 

Output

输出度度熊最多连续签到多少天。

 

Sample Input

2 1
1 1
3 3
1 2
1 1

 

Sample Output

3
3


 

题意

给定n段区间,问最多补m个位置的情况下最长的连续序列能有多长

题解

假设区间均不相交,那么我们可以通过二分答案,随后通过双指针O(n)来判断答案x是否满足,总共复杂度是O(n*log(n))的

双指针具体为:首先维护一个指针L指向第一个区间,R指向第一个区间,之后,我们进行如下操作:

判断R能否在耗费不大于m的情况下移动到下一个区间,若能,则更新m,并且R++;若不能,那么通过L++来紧缩区间,并且更新m

若其中产生了node[R].r-node[L].l>x,那么说明答案在[x+1,r)中,否则则在[l,x)中。

对题目所示区间相交的情况,可以通过以左端点为第一关键字,右端点为第二关键字进行排序,之后不断合并相交的区间

建议把区间都处理成左闭右开方便运算处理。

代码

 1 //HDU-6119 copyright:scidylanpno
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 const int MAXN =   100000+100;
 5 typedef long long ll;
 6 struct Node
 7 {
 8     ll l,r;
 9 }node[MAXN];
10 bool cmp(const Node x,const Node y)
11 {
12     return (x.l<y.l)||(x.l==y.l&&x.r<y.r);
13 }
14 bool check(Node *node,ll val,ll m,int n)
15 {
16     int L=1,R=1;
17     ll Max=0;
18     while(true)
19     {
20         if(R==n)
21         {
22             Max=max(Max,node[R].r-node[L].l+m);
23             break;
24         }
25         if(node[R+1].l-node[R].r>m)
26         {
27             Max=max(node[R].r-node[L].l+m,Max);
28             if(Max>val)    return true;
29             L++;
30             m+=node[L].l-node[L-1].r;
31         }else
32         {
33             R++;
34             m-=(node[R].l-node[R-1].r);
35         }
36     }
37     if(Max>val) return true;
38     return false;
39 }
40 
41 ll DC(Node *node,ll m,int n)
42 {
43     ll l=0,r=2000000000+2;
44     ll mid;
45     while(l<r)
46     {
47         mid=(l+r>>1);
48         if(check(node,mid,m,n)) l=mid+1;
49         else r=mid;
50     }
51     return l;
52 }
53 
54 void Run(int n)
55 {
56     ll m;
57     scanf("%lld",&m);
58     for(int i=1;i<=n;i++)
59     {
60         scanf("%lld%lld",&node[i].l,&node[i].r);
61         node[i].r++;
62     }
63     sort(node+1,node+1+n,cmp);
64     int i=1;
65     for(int j=2;j<=n;j++)
66     {
67         if(node[j].l>node[i].r)
68         {
69             i++;
70             node[i]=node[j];
71         }else
72         {
73             node[i].r=max(node[i].r,node[j].r);
74         }
75     }
76     n=i;
77     printf("%lld",DC(node,m,n));
78 }
79 int main()
80 {
81 
82     int n;
83     while(scanf("%d",&n)==1)
84     {
85         Run(n);
86         printf("\n");
87     }
88     return 0;
89 }

 

题解链接:http://www.cnblogs.com/scidylanpno/p/7355376.html

版权所有:scidylanpno

百度之星2017 HDU 6119 小小粉丝度度熊 二分+双指针