P11660 我终将成为你的倒影 题解

P11660 我终将成为你的倒影 题解

感觉评紫比较合理。

初步思路

b500,这于 n 相近,启发我们思考关于根号复杂度的做法。

考虑序列分块。散块暴力,难在整块。

最终思路

下取整可以看做取某个数的整数部分。f(x) 可以看为 xb+ab+[amodb+xmodbb]

容易发现,假若 f(x)=f(y),令 c=xbyb,那么有必要条件 |c|1

y1=xmodb,y2=ymodb,t=amodb

对于 c=0

  • y1+t<by2+t<by1+tby2+tb,即 t<min(by1,by2)tmax(by1,by2)。注意到这两个限制不交叉。

对于 c=1

  • y1+t<by2+tb,即 by2t<by1

对于 c=1

  • y1+tby2+t<b,即 by1t<by2

发现上述限制都是区间的形式,且 t<b。可以考虑在值域为 b 的桶上差分,再做前缀和。这样就可以支持 O(1) 查询整块内的答案。

b 很小,可以枚举。为对于每个块枚举所有的 b,对于所有块内的元素计算 f(Ai)=f(Ai1) 的限制,预处理出上述的数组。

空间复杂度 O(b2nB)B 为块长。

预处理时间复杂度 O(bn+b2nB)

注意

  1. 注意整块间的答案也要统计。
  2. 空间 O(b2nB),块长 B=n 时卡空间,可以适当调大。
  3. 注意限制本身是否合法,即防止出现左边大于右边。

为什么 Ai105,感觉复杂度于 Ai 没任何关系,可以开到 109

代码

#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);
  }
}

作者:ccxswl

出处:https://www.cnblogs.com/ccxswl/p/18698341

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   ccxswl  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up light_mode palette
选择主题