結果
| 問題 | No.3446 Range Adjacent Differences |
| ユーザー |
👑 |
| 提出日時 | 2026-02-10 09:48:39 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
AC
|
| 実行時間 | 1,348 ms / 2,200 ms |
| コード長 | 7,041 bytes |
| 記録 | |
| コンパイル時間 | 4,021 ms |
| コンパイル使用メモリ | 360,900 KB |
| 実行使用メモリ | 89,664 KB |
| 最終ジャッジ日時 | 2026-02-18 20:50:42 |
| 合計ジャッジ時間 | 21,287 ms |
|
ジャッジサーバーID (参考情報) |
judge5 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 26 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
// 64-ary predecessor structure for universe [0, 2^(6*LEVEL))
struct Pred64 {
static constexpr int LEVEL = 4; // 64^4 = 2^24
static constexpr int UNIV = 1 << (6 * LEVEL); // 2^24 = 16,777,216
array<vector<uint64_t>, LEVEL> d;
Pred64() {
for (int i = 0; i < LEVEL; ++i) {
int sz = 1 << (6 * (LEVEL - i - 1));
d[i].assign(sz, 0);
}
}
inline bool empty() const { return d[LEVEL - 1][0] == 0; }
inline void add(int x) {
unsigned ux = (unsigned)x;
for (int i = 0; i < LEVEL; ++i) {
unsigned idx = ux >> (6 * (i + 1));
unsigned bit = (ux >> (6 * i)) & 63U;
uint64_t &w = d[i][idx];
uint64_t before = w;
w |= 1ULL << bit;
if (w == before) break;
}
}
inline void remove(int x) {
unsigned ux = (unsigned)x;
for (int i = 0; i < LEVEL; ++i) {
unsigned idx = ux >> (6 * (i + 1));
unsigned bit = (ux >> (6 * i)) & 63U;
uint64_t &w = d[i][idx];
w &= ~(1ULL << bit);
if (w != 0) break;
}
}
// max element <= x, or -1 if none
inline int prev(int x) const {
if (empty()) return -1;
if (x < 0) return -1;
if (x >= UNIV) x = UNIV - 1;
unsigned ux = (unsigned)x;
// l=0: can take <= pos inside the same 64-bit word.
{
unsigned idx = ux >> 6;
unsigned pos = ux & 63U;
uint64_t mask = (pos == 63) ? ~0ULL : ((1ULL << (pos + 1)) - 1ULL);
uint64_t w = d[0][idx] & mask;
if (w) return (int)((idx << 6) | (unsigned)(63 - __builtin_clzll(w)));
}
// higher levels: must choose strictly smaller child than pos
for (int l = 1; l < LEVEL; ++l) {
unsigned idx = ux >> (6 * (l + 1));
unsigned pos = (ux >> (6 * l)) & 63U;
uint64_t mask = (pos == 0) ? 0ULL : ((1ULL << pos) - 1ULL); // bits < pos
uint64_t w = d[l][idx] & mask;
if (!w) continue;
int child = 63 - __builtin_clzll(w);
int res = (int)idx;
res = (res << 6) | child;
for (int t = l - 1; t >= 0; --t) {
uint64_t w2 = d[t][(unsigned)res];
int c = 63 - __builtin_clzll(w2);
res = (res << 6) | c;
}
return res;
}
return -1;
}
// min element >= x, or UNIV if none
inline int next(int x) const {
if (empty()) return UNIV;
if (x < 0) x = 0;
if (x >= UNIV) return UNIV;
unsigned ux = (unsigned)x;
// l=0: can take >= pos inside the same 64-bit word.
{
unsigned idx = ux >> 6;
unsigned pos = ux & 63U;
uint64_t mask = (~0ULL) << pos;
uint64_t w = d[0][idx] & mask;
if (w) return (int)((idx << 6) | (unsigned)__builtin_ctzll(w));
}
// higher levels: must choose strictly larger child than pos
for (int l = 1; l < LEVEL; ++l) {
unsigned idx = ux >> (6 * (l + 1));
unsigned pos = (ux >> (6 * l)) & 63U;
if (pos == 63) continue;
uint64_t mask = (~0ULL) << (pos + 1); // bits > pos
uint64_t w = d[l][idx] & mask;
if (!w) continue;
int child = __builtin_ctzll(w);
int res = (int)idx;
res = (res << 6) | child;
for (int t = l - 1; t >= 0; --t) {
uint64_t w2 = d[t][(unsigned)res];
int c = __builtin_ctzll(w2);
res = (res << 6) | c;
}
return res;
}
return UNIV;
}
};
static inline uint64_t hilbertOrder(int x, int y, int pow = 17, int rot = 0) {
if (pow == 0) return 0;
int h = 1 << (pow - 1);
int seg;
if (x < h) seg = (y < h) ? 0 : 1;
else seg = (y < h) ? 3 : 2;
seg = (seg + rot) & 3;
static const int rotateDelta[4] = {3, 0, 0, 1};
int nx = x & (h - 1);
int ny = y & (h - 1);
int nrot = (rot + rotateDelta[seg]) & 3;
uint64_t sub = hilbertOrder(nx, ny, pow - 1, nrot);
uint64_t add = (uint64_t)seg << (2 * pow - 2);
if (seg == 1 || seg == 2) return add + sub;
return add + ((1ULL << (2 * pow - 2)) - 1ULL - sub);
}
struct Query {
int l, r, x;
char c;
int idx;
uint64_t ord;
};
static const int MAXV = 10000000;
static vector<int> valCnt, gapCnt;
static Pred64 valSet, gapSet;
static vector<int> A;
static inline void add_gap(int g) {
int &cnt = gapCnt[g];
if (cnt == 0) gapSet.add(g);
++cnt;
}
static inline void remove_gap(int g) {
int &cnt = gapCnt[g];
--cnt;
if (cnt == 0) gapSet.remove(g);
}
static inline void add_index(int idx) {
int v = A[idx];
int &cv = valCnt[v];
if (cv == 0) {
int p = valSet.prev(v); // < v (since v not present)
int n = valSet.next(v); // > v (since v not present)
if (p != -1 && n != Pred64::UNIV) remove_gap(n - p);
if (p != -1) add_gap(v - p);
if (n != Pred64::UNIV) add_gap(n - v);
valSet.add(v);
cv = 1;
} else {
add_gap(0);
++cv;
}
}
static inline void remove_index(int idx) {
int v = A[idx];
int &cv = valCnt[v];
if (cv == 1) {
int p = valSet.prev(v - 1); // < v
int n = valSet.next(v + 1); // > v
if (p != -1) remove_gap(v - p);
if (n != Pred64::UNIV) remove_gap(n - v);
if (p != -1 && n != Pred64::UNIV) add_gap(n - p);
valSet.remove(v);
cv = 0;
} else {
remove_gap(0);
--cv;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, Q;
cin >> N >> Q;
A.assign(N + 1, 0);
for (int i = 1; i <= N; ++i) cin >> A[i];
valCnt.assign(MAXV + 1, 0);
gapCnt.assign(MAXV + 1, 0);
vector<Query> queries;
queries.reserve(Q);
for (int i = 0; i < Q; ++i) {
Query qu;
cin >> qu.l >> qu.r >> qu.x >> qu.c;
qu.idx = i;
qu.ord = hilbertOrder(qu.l - 1, qu.r - 1);
queries.push_back(qu);
}
sort(queries.begin(), queries.end(), [](const Query &a, const Query &b) {
return a.ord < b.ord;
});
vector<int> ans(Q, -1);
int curL = 1, curR = 0;
for (const auto &qu : queries) {
while (curL > qu.l) add_index(--curL);
while (curR < qu.r) add_index(++curR);
while (curL < qu.l) remove_index(curL++);
while (curR > qu.r) remove_index(curR--);
if (gapSet.empty()) { ans[qu.idx] = -1; continue; }
if (qu.c == 'L') {
int v = gapSet.prev(qu.x);
ans[qu.idx] = (v == -1) ? -1 : v;
} else {
int v = gapSet.next(qu.x);
ans[qu.idx] = (v == Pred64::UNIV) ? -1 : v;
}
}
for (int i = 0; i < Q; ++i) cout << ans[i] << '\n';
return 0;
}