百度之星初赛(B)--1006小小粉丝度度熊

1006:

小小粉丝度度熊(Hdu 6119)

题意:给n个区间,m个补签卡,区间内的天数是已经签到了的,否则没有签到,但是我们可以用补签卡补签。

问:最多能连续签到的天数。

思路:这道题跟某一次玲珑杯的题超级像,但是那道题简单一点。

首先我们 需要把重复的区间删除,和把可以连在一起的区间连在一起,所以先按照x从小到大,y从小到大排序,然后再进行区间合并。

然后再把后一个区间距离前一个区间的距离用qu数组存起来。

然后尝试着用M张签到表,尽可能的连接最长的区间,每次更新最大值,如果某一段qu的长度超过了m说明前后两个区间是没法连在一起的,那么就要重新连接,特别要考虑这里,前面一段区间的长度加上m可能使最大值,虽然没办法连接在一起,但有可能后面的区间超不过这段距离。然后就用一遍暴力即可。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define LL long long
#define siz 100005
#include <vector>
#include <queue>

using namespace std;
int n,m;
struct node{
    int x,y;
    bool operator <(const node &r)const{
        if(r.x==x) return y<r.y;
        return x<r.x;
    }
}gp[siz],in[siz];
int qu[siz];
void solve(){
    node u;
    u.x=u.y = -1;
    int cnt = 0;
    for(int i=1;i<=n;i++){
        if(u.x==-1){
            u.x = in[i].x;
            u.y = in[i].y;
        }
        else{
            if(u.x==in[i].x){
                u.y = in[i].y;
            }
            else{
                if(in[i].x<=u.y+1){
                    if(in[i].y>u.y)
                    u.y = in[i].y;
                }
                else{
                    gp[++cnt] = u;
                    u.x = in[i].x;
                    u.y = in[i].y;
                }
            }
        }
    }
    gp[++cnt] = u;
    int k =0;
    for(int i=2;i<=cnt;i++){
        qu[++k] = gp[i].x - gp[i-1].y -1;
    }
    qu[k+1] = 0;
   int x = 0;
   int s = 1;
   int ans = 0;
   for(int i=1;i<=cnt;i++){
        x += gp[i].y - gp[i].x + 1;
        ans = max(ans,x);
        //cout<<x<<endl;
        while(m<qu[i]&&s<i){
            ans = max(ans,x+m);
            m += qu[s];
            x -= qu[s];
            x = x - (gp[s].y - gp[s].x +1);
            ++s;
        }
        if(m>=qu[i]){
            x += qu[i];
            m -= qu[i];
            //cout<<1<<" "<<x<<endl;
            ans = max(ans,x);
        }
        else{
           // cout<<2<<" "<<x<<endl;
            ans = max(ans,x+m);
            x = 0;
            s = i+1;
        }
       // cout<<ans<<" "<<x<<endl;
   }
    if(m>0){
        x += m;
        ans = max(ans,x);
    }
    printf("%d\n",ans);
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        int gx,gy;
        for(int i = 1;i<=n;i++){
            scanf("%d%d",&in[i].x,&in[i].y);
        }
        sort(in+1,in+n+1);
        solve();
    }
    return 0;
}
/*
5 2
1 1
1 2
2 3
4 4
5 6

7 2
1 1
1 2
2 3
5 6
6 6
7 8
11 15
7 2
11 15
7 8
6 6
2 3
1 2
1 1
5 6


3 0
1 4
2 3
5 6

4 0
0 4
3 4
5 6
8 9


5 4
1 2
4 5
8 9
11 12
17 30

5 4
1 2
4 5
8 9
11 12
18 30

6 8
1 2
4 5
8 9
11 12
18 26
34 35

6 8
1 2
4 5
8 9
11 12
18 26
29 35

4 2
1 2
4 5
7 8
12 16

4 3
1 2
4 5
7 8
13 16
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值