1. 程式人生 > >HDU 6119 2017百度之星初賽B 小小粉絲度度熊 (二分)

HDU 6119 2017百度之星初賽B 小小粉絲度度熊 (二分)

端點 mission make miss 情況 others sin time 天都

小小粉絲度度熊

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 197 Accepted Submission(s): 78

Problem 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 Hint 樣例一:度度熊補簽第2天,然後第1天、第二天和第三天都進行了簽到操作。 樣例二:度度熊補簽第2天和第3天。 【分析】兩種做法。第一,雙指針掃一下,取最大值。第二,枚舉每一個塊作為右端點,然後向左二分左端點即可。不過區間可能 重疊交叉,所以要預處理一下,將區間合並。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define
met(a,b) memset(a,b,sizeof a) #define pb push_back #define mp make_pair #define rep(i,l,r) for(int i=(l);i<=(r);++i) #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 1e5+50;; const int M = 17; const int mod = 1e9+7; const int mo=123; const double pi= acos(-1.0); typedef pair<int,int>pii; int n,m; ll sum[N],sum2[N]; vector<pii>vec; struct man{ int l,r; }a[N]; bool cmp(const man &s,const man &d){ if(s.l==d.l)return s.r<d.r; return s.l<d.l; } int main(){ while(~scanf("%d%d", &n, &m)) { for(int i=1;i<=n;i++){ scanf("%d%d",&a[i].l,&a[i].r); } sort(a+1,a+1+n,cmp); int now=1; vec.clear(); met(sum,0);met(sum2,0); for(int i=2;i<=n;i++){ if(a[i].l<=a[now].r)a[now].r=max(a[now].r,a[i].r); else { vec.pb(mp(a[now].l,a[now].r)); now=i; } } vec.pb(mp(a[now].l,a[now].r)); int sz=vec.size(); ll ans=0,ss,dd; sum[0]=0; sum2[0]=vec[0].second-vec[0].first+1; for(int i=1;i<sz;i++){ sum[i]=sum[i-1]+vec[i].first-vec[i-1].second-1; sum2[i]=sum2[i-1]+vec[i].second-vec[i].first+1; } for(int i=0;i<sz;i++){ int ll=0,rr=i,res=-1; while(ll<=rr){ int mid=(ll+rr)/2; ss=sum[i]-sum[mid]; if(ss<=m)rr=mid-1,res=mid; else ll=mid+1; } if(res==0)dd=sum2[i]; else dd=sum2[i]-sum2[res-1]; ss=sum[i]-sum[res]; ans=max(ans,dd+ss+(m-ss)); } printf("%lld\n",ans); } return 0; }

HDU 6119 2017百度之星初賽B 小小粉絲度度熊 (二分)