小小粉丝度度熊

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+;;
const int M = ;
const int mod = 1e9+;
const int mo=;
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=;i<=n;i++){
scanf("%d%d",&a[i].l,&a[i].r);
}
sort(a+,a++n,cmp);
int now=;
vec.clear();
met(sum,);met(sum2,);
for(int i=;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=,ss,dd;
sum[]=;
sum2[]=vec[].second-vec[].first+;
for(int i=;i<sz;i++){
sum[i]=sum[i-]+vec[i].first-vec[i-].second-;
sum2[i]=sum2[i-]+vec[i].second-vec[i].first+;
}
for(int i=;i<sz;i++){
int ll=,rr=i,res=-;
while(ll<=rr){
int mid=(ll+rr)/;
ss=sum[i]-sum[mid];
if(ss<=m)rr=mid-,res=mid;
else ll=mid+;
}
if(res==)dd=sum2[i];
else dd=sum2[i]-sum2[res-];
ss=sum[i]-sum[res];
ans=max(ans,dd+ss+(m-ss));
}
printf("%lld\n",ans);
}
return ;
}
 
05-11 21:42