結果
| 問題 | No.3446 Range Adjacent Differences |
| ユーザー |
kidodesu
|
| 提出日時 | 2026-02-12 22:18:21 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 1,367 ms / 2,200 ms |
| コード長 | 4,999 bytes |
| 記録 | |
| コンパイル時間 | 2,354 ms |
| コンパイル使用メモリ | 199,596 KB |
| 実行使用メモリ | 56,192 KB |
| 最終ジャッジ日時 | 2026-02-18 20:51:28 |
| 合計ジャッジ時間 | 19,160 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 26 |
ソースコード
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const int MAX_VAL = 1 << 24;
const int D_SIZE = 20000005;
// --- 高速ヒルベルト順序計算 (反復版) ---
inline long long get_hilbert(int x, int y) {
long long d = 0;
// 2^19 は約 524,288 なので N=10^5 程度なら十分。必要に応じて調整
for (int s = 1 << 19; s > 0; s >>= 1) {
bool rx = x & s;
bool ry = y & s;
d += s * 1LL * s * ((3 * rx) ^ ry);
if (!ry) {
if (rx) {
x = (1 << 20) - 1 - x;
y = (1 << 20) - 1 - y;
}
swap(x, y);
}
}
return d;
}
// HierarchicalBitset の実装は変更なし(addの早期終了のみ維持)
struct HierarchicalBitset {
vector<uint64_t> layers[4];
HierarchicalBitset() {
layers[0].resize(1);
layers[1].resize(64);
layers[2].resize(4096);
layers[3].resize(262144);
}
inline void add(int a) {
for (int i = 3; i >= 0; --i) {
int a0 = a & 63;
a >>= 6;
if (layers[i][a] & (1ULL << a0)) return; // 既に立っていれば終了
layers[i][a] |= (1ULL << a0);
}
}
inline void dec(int a) {
for (int i = 3; i >= 0; --i) {
int a0 = a & 63;
a >>= 6;
layers[i][a] ^= (1ULL << a0);
if (layers[i][a]) break;
}
}
int bsl(int a) {
if (a < 0) return -1;
for (int i = 3; i >= 0; --i) {
uint64_t mask = (1ULL << (a & 63)) | ((1ULL << (a & 63)) - 1);
uint64_t x = layers[i][a >> 6] & mask;
if (x) {
int rep = ((a >> 6) << 6) | (63 - __builtin_clzll(x));
for (int j = i + 1; j < 4; ++j) {
rep = (rep << 6) | (63 - __builtin_clzll(layers[j][rep]));
}
return rep;
}
a = (a >> 6) - 1;
if (a < 0) break;
}
return -1;
}
int bsr(int a) {
if (a >= MAX_VAL) return -1;
for (int i = 3; i >= 0; --i) {
uint64_t mask = ~((1ULL << (a & 63)) - 1);
uint64_t x = layers[i][a >> 6] & mask;
if (x) {
int rep = ((a >> 6) << 6) | __builtin_ctzll(x);
for (int j = i + 1; j < 4; ++j) {
rep = (rep << 6) | __builtin_ctzll(layers[j][rep]);
}
return rep;
}
a = (a >> 6) + 1;
if (a >= (1 << (6 * i))) break;
}
return -1;
}
};
int D[D_SIZE];
int cnt0 = 0;
HierarchicalBitset X, Y;
// f0, f1 のロジックは変更なし
void f0(int a) {
D[a]++;
if (D[a] > 1) { cnt0++; return; }
int al = X.bsl(a - 1);
int ar = X.bsr(a + 1);
X.add(a);
if (al != -1 && ar != -1) {
int diff = ar - al;
if (--D[10000000 + diff] == 0) Y.dec(diff);
}
if (al != -1) {
int diff = a - al;
if (++D[10000000 + diff] == 1) Y.add(diff);
}
if (ar != -1) {
int diff = ar - a;
if (++D[10000000 + diff] == 1) Y.add(diff);
}
}
void f1(int a) {
D[a]--;
if (D[a] > 0) { cnt0--; return; }
X.dec(a);
int al = X.bsl(a - 1);
int ar = X.bsr(a + 1);
if (al != -1 && ar != -1) {
int diff = ar - al;
if (++D[10000000 + diff] == 1) Y.add(diff);
}
if (al != -1) {
int diff = a - al;
if (--D[10000000 + diff] == 0) Y.dec(diff);
}
if (ar != -1) {
int diff = ar - a;
if (--D[10000000 + diff] == 0) Y.dec(diff);
}
}
struct Query {
int t, l, r, x, id;
long long ord; // ヒルベルト順序を格納
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, q;
if (!(cin >> n >> q)) return 0;
vector<int> A(n);
for (int i = 0; i < n; ++i) cin >> A[i];
vector<Query> queries(q);
for (int i = 0; i < q; ++i) {
string c;
cin >> queries[i].l >> queries[i].r >> queries[i].x >> c;
queries[i].l--; // 0-indexed
queries[i].t = (c == "L" ? 0 : 1);
queries[i].id = i;
// クエリごとにヒルベルト順序を計算
queries[i].ord = get_hilbert(queries[i].l, queries[i].r);
}
// ヒルベルト順序でソート
sort(queries.begin(), queries.end(), [](const Query& a, const Query& b) {
return a.ord < b.ord;
});
vector<int> ans(q);
int nl = 0, nr = 0;
for (auto& qry : queries) {
while (qry.l < nl) f0(A[--nl]);
while (nr < qry.r) f0(A[nr++]);
while (nl < qry.l) f1(A[nl++]);
while (qry.r < nr) f1(A[--nr]);
if (qry.t == 0) {
int res = Y.bsl(qry.x);
ans[qry.id] = (cnt0 > 0) ? max(res, 0) : res;
} else {
ans[qry.id] = Y.bsr(qry.x);
}
}
for (int x : ans) cout << x << "\n";
return 0;
}
kidodesu