首页 > 代码库 > 百度之星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 小小粉丝度度熊 二分+双指针