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

ccxswl
傻不拉几的搬运于
2025-08-24 23:09:14,当前版本为作者最后更新于2025-02-04 17:28:45,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
P11660 我终将成为你的倒影 题解
感觉评紫比较合理。
初步思路
,这于 相近,启发我们思考关于根号复杂度的做法。
考虑序列分块。散块暴力,难在整块。
最终思路
下取整可以看做取某个数的整数部分。 可以看为 $\lfloor \frac x b \rfloor + \lfloor \frac a b \rfloor + [a \bmod b + x \bmod b \ge b]$。
容易发现,假若 ,令 $c = \lfloor \frac x b \rfloor - \lfloor \frac y b \rfloor$,那么有必要条件 。
令 。
对于 :
- 有 或 ,即 或 。注意到这两个限制不交叉。
对于 :
- 有 ,即 。
对于 :
- 有 ,即 。
发现上述限制都是区间的形式,且 。可以考虑在值域为 的桶上差分,再做前缀和。这样就可以支持 查询整块内的答案。
很小,可以枚举。为对于每个块枚举所有的 ,对于所有块内的元素计算 的限制,预处理出上述的数组。
空间复杂度 , 为块长。
预处理时间复杂度 。
注意
- 注意整块间的答案也要统计。
- 空间 ,块长 时卡空间,可以适当调大。
- 注意限制本身是否合法,即防止出现左边大于右边。
为什么 ,感觉复杂度于 没任何关系,可以开到 。
代码
#include <bits/stdc++.h> using namespace std; #define IL inline #define vec vector #define eb emplace_back #define bg begin #define emp emplace #define fi first #define se second #define bg begin #define lb lower_bound using dub = double; using ubt = long long; using pii = pair<int, int>; IL void ckx(int &x, const int &y) { (x < y) && (x = y); } IL void ckm(int &x, const int &y) { (x > y) && (x = y); } template <typename T = int> IL T _R() { T s = 0, w = 1; char c = getchar(); while (!isdigit(c)) w = c == '-' ? -1 : 1, c = getchar(); while (isdigit(c)) s = s * 10 + c - 48, c = getchar(); return s * w; } const int N = 1e5; const dub alpha = 1.3; const int B = alpha * sqrt(N); const int S = N / B + 1; const int K = 500; const int maxN = N + 3, maxK = K + 3, maxS = S + 3; int n, m, x[maxN]; int pos[maxN], L[maxS], R[maxS]; int t[maxS][maxK][maxK]; int main() { n = _R(), m = _R(); for (int i = 1; i <= n; i++) x[i] = _R(); for (int i = 1; i <= n; i++) { pos[i] = (i - 1) / B + 1; if (!L[pos[i]]) L[pos[i]] = i; R[pos[i]] = i; } for (int u = 1; u <= pos[n]; u++) { for (int b = 1; b <= K; b++) { for (int i = L[u] + 1; i <= R[u]; i++) { int c = x[i] / b - x[i - 1] / b; if (abs(c) <= 1) { int y1 = x[i] % b, y2 = x[i - 1] % b; if (c == 0) { t[u][b][0]++, t[u][b][min(b - y1, b - y2)]--; t[u][b][max(b - y1, b - y2)]++; } else if (c == 1) { if (y1 >= y2) continue; t[u][b][b - y2]++, t[u][b][b - y1]--; } else { if (y1 <= y2) continue; t[u][b][b - y1]++, t[u][b][b - y2]--; } } } for (int i = 1; i <= K; i++) t[u][b][i] += t[u][b][i - 1]; } } int ans = 0; while (m--) { int l = _R(), r = _R(), a = _R(), b = _R(); l ^= ans, r ^= ans, a ^= ans, b ^= ans; if (l >= r) { printf("%d\n", ans = 0); continue; } ans = 0; if (pos[l] == pos[r]) { for (int i = l + 1; i <= r; i++) ans += (x[i] + a) / b == (x[i - 1] + a) / b; } else { for (int i = l + 1; i <= R[pos[l]]; i++) ans += (x[i] + a) / b == (x[i - 1] + a) / b; for (int i = L[pos[r]] + 1; i <= r; i++) ans += (x[i] + a) / b == (x[i - 1] + a) / b; for (int i = pos[l] + 1; i < pos[r]; i++) ans += t[i][b][a % b]; for (int i = pos[l]; i < pos[r]; i++) ans += (x[R[i]] + a) / b == (x[R[i] + 1] + a) / b; } printf("%d\n", ans); } }
- 1
信息
- ID
- 11288
- 时间
- 1000ms
- 内存
- 250MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者