怎样更有力气

题目描述

OI 大师抖儿在夺得银牌之后,顺利保送 pku。这一天,抖儿问长者:“我虽然已经保送了,但我的志向是为国家健康工作五十年。请问我应该怎样变得更有力气?”

长者回答:“你啊,Too Young Too Simple,Sometimes Naive!如果你想要我教你,你要先进行艰苦的修行。”

长者的住宅中有一堵长度为 n 的墙。每天抖儿起床修行,会选择一段长度为 x 的区间染成白色。长者的住宅附近有一群香港记者,为了借助抖儿拜访长者,第 i 天香港记者会将区间[l i ,r i ]染成白色来讨好抖儿(也就是说,每天墙会被抖儿和香港记者各染一次)。现在抖儿已经预先知道了香港记者的动向,他想知道他最少几天就能把墙全部染白,完成修行。


输入

第一行三个整数 n,m,x,分别表示墙的长度,天数和区间的长度。

接下来 m 行,每行两个整数 l i 、r i ,表示香港记者在第 i 天会将区间[l i ,r i ]染成白色。


输出


一行一个整数,表示抖儿最少几天能把墙全部染白。如果 m 天之后依然无法染白,则输出“Poor Douer!”


样例输入

10 3 3
2 5
4 8
9 10


样例输出

2

 

 

对于所有的数据,保证 n≤1018 ,m≤100000,x≤n 且数据随机



题解

二分答案。

二分需要的天数mid,然后把前mid天的区间排序,随便搞搞就可以了。

注意x=0 的情况要特判一下。

 

#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long

const int maxm=100000+50;

ll n,m,x;

struct A{ll l,r;}a[maxm];
struct B{ll l,r;}b[maxm];
int cmp(const B &a,const B &b){
    if(a.l==b.l) return a.r<b.r;
    return a.l<b.l;
}

bool check(int len){
    memset(b,0,sizeof(b));
    ll ans=0,R=0,sum=0;
    for(int i=1;i<=len;i++) b[i].l=a[i].l,b[i].r=a[i].r;
    sort(b+1,b+1+len,cmp);
    if(x==0){
        if(b[1].l!=1) return false;
        if(b[len].r!=n) return false;
        for(int i=1;i<=len;i++){
            if(b[i].l>R+1) return false;
            R=max(R,b[i].r);
        }
        if(R!=n) return false;
        return true;
    }
    for(int i=1;i<=len;i++){
        if(b[i].l>R+1){
            sum=(b[i].l-R-1)/x;
            if((b[i].l-R-1)%x!=0) sum++;
        }
        else sum=0;
        R=max(b[i].r,sum*x+R);
        ans+=sum;
        if(ans>len) return false;
    }
    sum=(n-R)/x;
    if((n-R)%x!=0) sum++;
    if(n>R) ans+=sum;
    if(ans>len) return false;
    return true;
}

template<typename T>void read(T& aa){
    char cc; ll ff;aa=0;cc=getchar();ff=1;
    while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int main(){
//    freopen("liqi.in","r",stdin);
//    freopen("liqi.out","w",stdout);
    read(n),read(m),read(x);
    for(int i=1;i<=m;i++) read(a[i].l),read(a[i].r);
    int l=0,r=m;
    if(!check(m)){
        cout<<"Poor Douer!"<<endl;
        return 0;
    }
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid)) r=mid-1;
        else l=mid+1;
    }
    cout<<l<<endl;
    return 0;
}

 

posted @ 2018-10-26 19:13  rld  阅读(214)  评论(0编辑  收藏  举报