首页 > 代码库 > hdu 6110 …&&百度之星 T6

hdu 6110 …&&百度之星 T6

小小粉丝度度熊

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天。
———————————————————————————————
这道题读入后要先初始化一波 使得相邻块之间没有交点
这道题维护两个指针 l r 
l 维护是当前的左端点 r是右端点
r先向右走 如果cost超过m就挪左端点就好了
技术分享
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=100007;
int read(){
    int ans=0,f=1,c=getchar();
    while(c<0||c>9){if(c==-) f=-1; c=getchar();}
    while(c>=0&&c<=9){ans=ans*10+(c-0); c=getchar();}
    return ans*f;
}
int n,m,cnt,nl,nr,ans,sum;
struct node{
    int l,r;
    bool operator<(const node &x)const{return l<x.l;}
}e[M],q[M];
int cal(int x){return x?q[x].l-q[x-1].r:0;}
int main()
{
    while(scanf("%d %d",&n,&m)==2){
        for(int i=0;i<n;i++) e[i].l=read(),e[i].r=read()+1;
        sort(e,e+n);
        cnt=0; int ll=e[0].l,rr=e[0].r;
        for(int i=1;i<n;i++){
            if(e[i].r<=rr) continue;
            if(e[i].l<=rr) rr=e[i].r;
            else q[++cnt]=(node){ll,rr},ll=e[i].l,rr=e[i].r;
        }
        q[++cnt]=(node){ll,rr};
        ans=0;
        for(int i=0,j=0,cost=0;i<=cnt;i++){
            int s=q[i].r-q[j].l;
            cost+=cal(i);
            while(cost>m){
                j++;
                s=q[i].r-q[j].l;
                cost-=cal(j);
            }
            ans=max(ans,s-cost+m);
        }printf("%d\n",ans);
    }
    return 0;
}
View Code

 

hdu 6110 …&&百度之星 T6