题目大意:
有 (n) 组防具。第 (i) 个防具会标记在区间 ([S_i,E_i]) 中模 (D_i) 的值是 (S_imod D_i) 的位置。求哪个位置被标记了奇数次。
正文:
我们可以考虑二分。那么找一下题目中隐藏的单调性。
可以发现,我们可以用一段区间的标记总值作为 key,比如当前二分到 ([l,r]),我们可以先判断 ([l,mid]) 的是否为奇数。如果是,则缩短范围到 ([l,mid]);若不是,说明 ([mid+1,r]) 必有一点是奇数,则缩小范围至 ([mid+1,r])。
代码:
const int N = 2e5 + 10;
int t, n;
ll a[N][3];
ll calc(ll r)
{
ll ans = 0;
for (int i = 1; i <= n; i++)
{
if (a[i][0] > r) continue;
ans += (min(r, a[i][1]) - a[i][0]) / a[i][2] + 1;
}
return ans;
}
bool check (ll l, ll r)
{
return (calc(r) - calc(l - 1)) % 2;
}
int main()
{
ll l, r;
scanf ("%d", &t);
for (; t--; )
{
scanf ("%d", &n);
r = 0ll, l = 1ll << 40;
for (int i = 1; i <= n; i++)
{
scanf ("%lld%lld%lld", &a[i][0], &a[i][1], &a[i][2]);
l = min (l, a[i][0]);
r = max (r, a[i][1]);
}
if (!check(l, r)) {puts("There's no weakness."); continue;}
while (l <= r)
{
ll mid = l + r >> 1ll;
if (check(l, mid))
r = mid - 1;
else
l = mid + 1;
}
printf ("%lld %lld
", l, calc(l) - calc(l - 1));
}
return 0;
}