百度之星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 小小粉絲度度熊 二分+雙指針