HDU 4768 Flyer(二分)

来源:互联网 发布:瘦骨精油副作用知乎 编辑:程序博客网 时间:2024/04/29 12:22

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4768

题目很二分想法很好实现,但是想到不容易,开始拿到这个题目打死也没想到是二分,队友和我都当数学题去做,后来发现二分,原来二分也可以这么经典

这个题目数据范围很大,时间给的很少,肯定是个线性算法或者n*log(n)的算法

二分要解决的关键问题是向左还是向右,看题目给的条件,最多只有一个点是奇数个,那么就以当前点为分界点(自己算左边),看左边的传单总数量

如果奇数,那么答案一定在左边,如果不是在答案存在的情况下一定在右边!

#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>using namespace std;#define maxn 30000#define inf 1e10#define LL __int64#define MIN(a,b) (a<b?a:b)#define MAX(a,b) (a>b?a:b)struct point{    LL a,b,c;}po[maxn];LL n,a,b;LL find_num_left(LL pos){    LL i,ans=0;    for(i=0;i<n;i++)    if(po[i].b<=pos) ans+=(po[i].b-po[i].a)/po[i].c+1;    else if(po[i].a<=pos && po[i].b>=pos) ans+=(pos-po[i].a)/po[i].c+1;    return ans;}int solve(){    LL i,j,k,mid,num;    while(a<=b){        mid=(a+b)/2;        num=find_num_left(mid);        if(num%2==1) b=mid;        else a=mid+1;//这里要+1,因为在计算的时候mid是包含在左边界的,现在左边界不满足,故mid也要排除        if(a==b) break;    }    num=0;    for(i=0;i<n;i++) if(a>=po[i].a && a<=po[i].b && (a-po[i].a)%po[i].c==0) num++;    if(num%2==0){        printf("DC Qiang is unhappy.\n");        return 0;    }    printf("%I64d %I64d\n",a,num);    return 0;}int main(){    LL i,j,k;    while(scanf("%I64d",&n)!=EOF){        a=inf,b=-1;        for(i=0;i<n;i++){            scanf("%I64d%I64d%I64d",&po[i].a,&po[i].b,&po[i].c);            a=MIN(a,po[i].a),b=MAX(b,po[i].b);        }        solve();    }    return 0;}


原创粉丝点击