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;
}