1. 程式人生 > >百度之星2017 HDU 6119 小小粉絲度度熊 二分+雙指針

百度之星2017 HDU 6119 小小粉絲度度熊 二分+雙指針

out center 天都 blank esp 大於 rip max bre

小小粉絲度度熊

題目鏈接: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 小小粉絲度度熊 二分+雙指針