1 条题解
-
0
自动搬运
来自洛谷,原作者为

kai586123
啊嗯搬运于
2025-08-24 22:14:27,当前版本为作者最后更新于2019-12-16 21:57:07,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
异或大问题当然是一位一位算啦~枚举每一位,算可能的答案中这一位有多少有多少就好。
发现结果和行,列都有关,且很小,可以考虑枚举行,计算这一行有多少满足要求的。
对建一棵可持久化Trie,询问的时候每一行维护一下走到了Trie的哪里,根据数量决定走哪边就好了。
#include <bits/stdc++.h> inline int rd() { int a = 1, b = 0; char c = getchar(); while (!isdigit(c)) a = c == '-' ? 0 : 1, c = getchar(); while (isdigit(c)) b = b * 10 + c - '0', c = getchar(); return a ? b : -b; } const int N = 3e5 + 233; int n, m, X[N], Y[N], p, pt[N][2]; int ch[N * 35][2], sum[N * 35], tot, root[N]; inline int insert(int pre, int val) { int now = ++tot, ret = now; for (int i = 31; ~i; --i) { int t = (val >> i) & 1; ch[now][t ^ 1] = ch[pre][t ^ 1]; pre = ch[pre][t]; now = ch[now][t] = ++tot; sum[now] = sum[pre] + 1; } return ret; } inline int solve(int x1, int x2, int y1, int y2, int k) { k = (x2 - x1 + 1) * (y2 - y1 + 1) - k + 1; for (int i = x1; i <= x2; ++i) { pt[i][0] = root[y1 - 1]; pt[i][1] = root[y2]; } int ret = 0; for (int s = 31; ~s; --s) { int cnt = 0; for (int i = x1; i <= x2; ++i) { int t = (X[i] >> s) & 1; cnt += sum[ch[pt[i][1]][t]] - sum[ch[pt[i][0]][t]]; } int nxt = k <= cnt ? 0 : 1; if (nxt) k -= cnt; ret = (ret << 1) | nxt; for (int i = x1; i <= x2; ++i) { int t = ((X[i] >> s) & 1) ^ nxt; pt[i][0] = ch[pt[i][0]][t]; pt[i][1] = ch[pt[i][1]][t]; } } return ret; } int main() { n = rd(), m = rd(); for (int i = 1; i <= n; ++i) X[i] = rd(); for (int i = 1; i <= m; ++i) { Y[i] = rd(); root[i] = insert(root[i - 1], Y[i]); } p = rd(); while (p--) { int x1 = rd(), x2 = rd(), y1 = rd(), y2 = rd(), k = rd(); printf("%d\n", solve(x1, x2, y1, y2, k)); } return 0; }
- 1
信息
- ID
- 4649
- 时间
- 2000ms
- 内存
- 500MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者