1 条题解
-
0
首先我们可以发现 A 与 B 同时走一步相当于 A 走两步。假设这两步他选的是 与 ,原来的位置为 ,那么他会到达 。
那么问题转化为是否存在一组解,使得有这样一个式子成立。
我们把它化成差分形式,把差分数组单独记为 。
$$2\sum _ {i = 1} ^ k (c_{2i} - c_{2i - 1}) = 2\sum _{i=1}^k d_i = b - a$$不难发现,这个问题可以用裴蜀定理。具体地,可参考 this,可以得到有解当且仅当 。
那么这个问题就可以用二分解决了。具体的,我们可以将 差分后按 排序,然后我们对每个询问,二分 表示选 在 到 这段区间里的节点是否有解即可。
再加上多组询问互相独立,可以用整体二分,再用线段树维护区间 即可。
::::info[Code]
#include <bits/stdc++.h> using namespace std; bool st; const int N = 5e4 + 5; int n, m; struct Seg { int tree[N << 2]; void pushup (int node) { tree[node] = __gcd (tree[node << 1], tree[(node << 1) + 1]); } void modify (int node, int l, int r, int s, int c) { if (l == r) { tree[node] = c; return ; } int mid = l + ((r - l) >> 1); if (s <= mid) modify (node << 1, l, mid, s, c); else modify ((node << 1) + 1, mid + 1, r, s, c); pushup (node); } int query (int node, int l, int r, int s, int t) { if (s <= l && r <= t) return tree[node]; int mid = l + ((r - l) >> 1), ret = 0; if (s <= mid) ret = __gcd (ret, query (node << 1, l, mid, s, t)); if (t > mid) ret = __gcd (ret, query ((node << 1) + 1, mid + 1, r, s, t)); return ret; } } T; struct node { int id, c, f; bool operator < (const node &T) const { return f < T.f; } } a[N], b[N]; struct Query { int id, l, r, a, b; } q[N], q1[N], q2[N]; int ans[N]; void solve (int l, int r, int L, int R) { if (L == R) { T.modify (1, 1, n, b[L].id, b[L].c); for (int i = l; i <= r; ++i) { long long tmp = 2 * T.query (1, 1, n, q[i].l, q[i].r); // 判无解记得判 gcd != 0 if (!tmp || (q[i].b - q[i].a) % tmp) ans[q[i].id] = -1; else ans[q[i].id] = b[L].f; } T.modify (1, 1, n, b[L].id, 0); return ; } int mid = L + ((R - L) >> 1), cnt1 = 0, cnt2 = 0; for (int i = L; i <= mid; ++i) T.modify (1, 1, n, b[i].id, b[i].c); for (int i = l; i <= r; ++i) { long long tmp = 2 * T.query (1, 1, n, q[i].l, q[i].r); if (!tmp || (q[i].b - q[i].a) % tmp) q2[++cnt2] = q[i]; else q1[++cnt1] = q[i]; } for (int i = 1; i <= cnt1; ++i) q[l + i - 1] = q1[i]; for (int i = 1; i <= cnt2; ++i) q[l + cnt1 + i - 1] = q2[i]; solve (l + cnt1, r, mid + 1, R); for (int i = L; i <= mid; ++i) T.modify (1, 1, n, b[i].id, 0); solve (l, l + cnt1 - 1, L, mid); } bool ed; int main () { ios::sync_with_stdio (false); cin.tie (0); cout.tie (0); cerr << "[Memory] " << (&st - &ed) / 1024 / 1024 << " MB\n"; cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> a[i].c; for (int i = 1; i <= n; ++i) cin >> a[i].f; sort (a + 1, a + n + 1); for (int i = 1; i < n; ++i) b[i] = {i + 1, a[i + 1].c - a[i].c, a[i + 1].f - a[i].f}; sort (b + 1, b + n); for (int i = 1; i <= m; ++i) { cin >> q[i].a >> q[i].b >> q[i].l >> q[i].r; q[i].id = i; q[i].l = lower_bound (a + 1, a + n + 1, (node){0, 0, q[i].l}) - a + 1; q[i].r = upper_bound (a + 1, a + n + 1, (node){0, 0, q[i].r}) - a - 1; if (q[i].l > q[i].r) ans[i] = -1; } solve (1, m, 1, n - 1); for (int i = 1; i <= m; ++i) cout << ans[i] << ' '; return 0; }::::
- 1
信息
- ID
- 7314
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者