hud4768(Flyer)详解,二分搜索

来源:互联网 发布:js弹出窗口居中 编辑:程序博客网 时间:2024/05/21 22:38

题目链接:点击打开链接

需要注意的点是:

1.如何表示这些票发给了某人(开始我想的是用数组,然后数组下标代表人,数组中存票数,不过这里数据量太大,不可)。

2.通过奇,偶性来知道要找的人在那个区间。

3.如何定义较大的数据变量。

4.二分搜索结束后,想找的人如何表示

#include<cstdio>#include<iostream>#include<algorithm>using namespace std;int n;long long a[200001], b[200001], c[200001];long long cal(long long mid){//本函数用于判断截止到mid发出去的传单数量    int sum = 0;    for(int i = 0; i < n; i++){//用来求总的发传单的次数        long long x = min(b[i], mid);//x用来表示最左端到mid的距离,但是当b[i]<mid的时候,只算到b[i],就足够了        if(x>=a[i])//需要保证x在a[i]右边            sum += (x-a[i])/c[i] + 1;//求单个社团传单的次数,例如(20-5)/7 = 2,而这里还有计算上5本身也有一张票所以再加1    }    return sum;}void solve(){    long long l, r, mid, sum;    l = 0; r = 1LL << 31;//学生总数为1到2^32,1LL是2^64,位运算31后是2^33    while(l < r){        mid = (l + r)/2;        sum = cal(mid);        if(sum%2 == 0) l = mid + 1;//当返回值(从左到中的发出去的票数)为偶数,说明该学生在右边        else r = mid;    }    if(l == 1LL << 31)//找完也没有        printf("DC Qiang is unhappy.\n");    else{        while(cal(r)%2 == 0) r++;//因为r和l交错后循环结束,所以向右寻找合适的r(也可向左寻找合适的l)        cout<<r<<' '<<cal(r)-cal(r-1)<<endl;    }}int main(){    while(scanf("%d", &n) != EOF){        for(int i = 0; i < n; i++){            scanf("%d%d%d", &a[i], &b[i], &c[i]);        }        solve();    }    return 0;}


原创粉丝点击