1. 程式人生 > 實用技巧 >AcWing 120 防線(二分)

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.\n");
        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\n",l,cnt);
        }
    }
    return 0;
}