CF2089B2 Canteen (Hard Version) 题解
嗯?这不是模拟题吗?
一个纯模拟做法,无法从 Easy Version 导出。
时间复杂度
当一个
最初共
考虑用两个 bitset 分别维护
通过模拟,可以得知每一轮
这里手写 bitset,减少每个有效操作的代价是
由于一些原因,这里
int n, a[MAXN], b[MAXN], tim, mx;
ull W, k, S, Sn;
struct {
ull val[3200];
il int query(int i) {
return val[i >> 6] >> (i & 63) & 1;
}
il void change(int i) {
val[i >> 6] ^= 1ull << (i & 63);
}
il void right() {
int p = query(n - 1);
rep2(i, mx, 1) {
val[i] <<= 1;
val[i] |= val[i - 1] >> 63;
} val[0] <<= 1; val[0] |= p;
}
il void init() {
rep1(i, 0, mx) val[i] = -1;
}
} bal, cas;
il void find() {
rep1(i, 0, mx) if (W = (bal.val[i] & cas.val[i])) {
int pre = i << 6;
rep1(j, 0, 63) if (W >> j & 1) {
int x = pre + j, y = x < tim ? x - tim + n : x - tim, t = min(b[x], a[y]);
if (x >= n) break;
Sn += t;
if (!(a[y] -= t)) bal.change(x);
if (!(b[x] -= t)) cas.change(x);
}
}
}
il void solve() {
read(n, k); mx = n - 1 >> 6; bal.init(); cas.init(); tim = S = Sn = 0;
rer(i, 0, n - 1, a), S += a[i]; rer(i, 0, n - 1, b);
if (k >= S) return puts("0"), void();
while (true) {
find(), ++tim;
if (Sn + k >= S) return printf("%d\n", tim), void();
bal.right();
}
}
int main() {
for (int T = read(); T--; ) solve();
return 0;
}