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

小小粉丝度度熊

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;
}

 

 
posted @ 2017-08-13 19:32  贱人方  阅读(213)  评论(0编辑  收藏  举报