AcWing 120 防线(二分)

题目链接

解题思路

  这题可以很巧妙的用二分来解决,因为最多只含一个奇数,所以我们可以二分奇数位置。如果总的防具数是偶数,那么就没有破绽,否则,如果左区间的防具数是奇数,那么答案肯定在左区间,如果右区间的防具数是奇数,那么答案就在右区间。

代码

const int maxn = 2e5+10;
struct INFO {
    ll s,e,d;
} info[maxn];
int n;
bool check(ll x) {
    ll sum = 0;
    for (int i = 1; i<=n; ++i)
        if (info[i].s<=x) sum += 1+(min(x,info[i].e)-info[i].s)/info[i].d;
    return sum&1;    
}
int main() {
    int t; scanf("%d",&t);
    while(t--) {
        scanf("%d",&n);
        for (int i = 1; i<=n; ++i) scanf("%lld%lld%lld",&info[i].s,&info[i].e,&info[i].d);
        ll l = 0, r = 12345678910LL;
        while(l<r) {
            ll mid = (l+r)>>1;
            if (check(mid)) r = mid;
            else l = mid+1;
        }
        if (r==12345678910LL) printf("There's no weakness.
");
        else {
            int cnt = 0;
            for (int i = 1; i<=n; ++i) 
                if (info[i].s==l || (info[i].e>=l && info[i].s<=l && (l-info[i].s)%info[i].d==0)) ++cnt;
            printf("%lld %d
",l,cnt);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/13304799.html