P11660 我终将成为你的倒影 题解
P11660 我终将成为你的倒影 题解
感觉评紫比较合理。
初步思路
考虑序列分块。散块暴力,难在整块。
最终思路
下取整可以看做取某个数的整数部分。
容易发现,假若
令
对于
- 有
或 ,即 或 。注意到这两个限制不交叉。
对于
- 有
,即 。
对于
- 有
,即 。
发现上述限制都是区间的形式,且
空间复杂度
预处理时间复杂度
注意
- 注意整块间的答案也要统计。
- 空间
,块长 时卡空间,可以适当调大。 - 注意限制本身是否合法,即防止出现左边大于右边。
为什么
代码
#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);
}
}
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探