結果
| 問題 | No.3452 Divide Permutation |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2026-02-25 22:25:10 |
| 言語 | C++23 (gcc 15.2.0 + boost 1.89.0) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 5,905 bytes |
| 記録 | |
| コンパイル時間 | 3,795 ms |
| コンパイル使用メモリ | 349,604 KB |
| 実行使用メモリ | 39,564 KB |
| 最終ジャッジ日時 | 2026-02-25 22:26:01 |
| 合計ジャッジ時間 | 43,597 ms |
|
ジャッジサーバーID (参考情報) |
judge6 / judge1 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 45 RE * 24 |
ソースコード
// Author: lzm0107
#include <bits/stdc++.h>
using namespace std;
constexpr int kMod = 998'244'353, kInf32 = 0x3f3f3f3f;
constexpr int kMaxN = 200'000;
int pw10[kMaxN * 2 + 10];
struct Info0 {
int min_val, max_val, hash_val, len;
Info0() : min_val(kInf32), max_val(~kInf32), hash_val(0), len(0) {}
Info0(int _min_val, int _max_val, int _hash_val, int _len) : min_val(_min_val), max_val(_max_val), hash_val(_hash_val), len(_len) {}
Info0 operator+(Info0 rhs) const {
return {
min(min_val, rhs.min_val),
max(max_val, rhs.max_val),
(int)(((long long)hash_val * pw10[rhs.len] + rhs.hash_val) % kMod),
len + rhs.len};
}
Info0 &operator+=(Info0 rhs) {
return *this = *this + rhs;
}
};
struct Info1 {
Info0 d;
int min_head, max_head;
bool chance;
Info1() : d(), min_head(kInf32), max_head(~kInf32), chance(false) {}
Info1(Info0 _d, int x) : d(_d), min_head(x), max_head(x), chance(_d.min_val < x) {}
Info1(Info0 _d, int _min_head, int _max_head, bool _chance) : d(_d), min_head(_min_head), max_head(_max_head), chance(_chance) {}
Info1 operator+(Info1 rhs) const {
return {
d + rhs.d,
min(min_head, rhs.min_head),
max(max_head, rhs.max_head),
chance || rhs.chance || max_head > rhs.d.min_val || d.max_val > rhs.min_head};
}
Info1 &operator+=(Info1 rhs) {
return *this = *this + rhs;
}
};
struct SegmentTree0 {
Info0 d[(4 << __lg(kMaxN + 1)) + 10];
int pn;
void Build(int *arr, int n) {
pn = 2 << (31 ^ __builtin_clz(n + 1));
for (int i = 1; i < pn * 2; i++) {
d[i] = Info0();
}
for (int i = 1; i <= n; i++) {
d[i + pn] = {arr[i], arr[i], arr[i], 1};
}
for (int i = pn - 1; i >= 1; i--) {
d[i] = d[i << 1] + d[i << 1 | 1];
}
}
Info0 Query(int l, int r) {
Info0 res_l, res_r;
for (l += pn - 1, r += pn + 1; l ^ r ^ 1; l >>= 1, r >>= 1) {
if (l & 1 ^ 1) {
res_l += d[l ^ 1];
}
if (r & 1) {
res_r = d[r ^ 1] + res_r;
}
}
return res_l + res_r;
}
int FindFirstGE(int pos, int val) {
for (pos += pn; pos > 0 && ((pos & 1) || d[pos ^ 1].max_val < val); pos >>= 1) {}
if (pos == 0) {
return -1;
}
for (pos ^= 1; pos < pn; pos = pos << 1 | (d[pos << 1].max_val < val)) {}
return pos - pn;
}
} sgt0;
struct SegmentTree1 {
Info1 d[(4 << __lg(kMaxN + 1)) + 10];
int pn;
void Build(int n) {
pn = 2 << (31 ^ __builtin_clz(n + 1));
for (int i = 1; i < pn * 2; i++) {
d[i] = Info1();
}
}
void Set(int pos, Info1 val) {
pos += pn;
d[pos] = val;
for (pos >>= 1; pos > 0; d[pos] = d[pos << 1] + d[pos << 1 | 1], pos >>= 1) {}
}
array<int, 3> FindBetterSuffix() {
Info1 sum;
int pos = 1;
for (; pos < pn;) {
if (d[pos << 1].chance ||
d[pos << 1].max_head > min(d[pos << 1 | 1].d.min_val, sum.d.min_val) ||
d[pos << 1].d.max_val > min(d[pos << 1 | 1].min_head, sum.min_head)) {
sum = d[pos << 1 | 1] + sum;
pos <<= 1;
} else {
pos = pos << 1 | 1;
}
}
return {pos - pn, min(d[pos].d.min_val, sum.d.min_val), sum.min_head};
}
} sgt1;
int n, p[kMaxN + 10];
set<int> segment_start;
void Flip(int x) {
int l, r;
if (segment_start.count(x)) {
auto it = segment_start.find(x);
l = *prev(it), r = *next(it);
segment_start.erase(it);
sgt1.Set(p[l], Info1(sgt0.Query(l, r - 1), p[l]));
sgt1.Set(p[x], Info1());
} else {
auto it = segment_start.insert(x).first;
l = *prev(it), r = *next(it);
sgt1.Set(p[l], Info1(sgt0.Query(l, x - 1), p[l]));
sgt1.Set(p[x], Info1(sgt0.Query(x, r - 1), p[x]));
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
pw10[0] = 1;
for (int i = 1; i <= kMaxN; i++) {
pw10[i] = 10ll * pw10[i - 1] % kMod;
}
int T;
cin >> T;
while (T--) {
static int ans[kMaxN + 10], q[kMaxN + 10];
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> p[i];
q[p[i]] = i;
}
sgt0.Build(p, n);
sgt1.Build(n);
sgt1.Set(p[1], Info1(sgt0.Query(1, n), p[1]));
segment_start = {1, n + 1};
for (int cur = 0; cur <= n; cur++) {
ans[segment_start.size() - 1] = sgt1.d[1].d.hash_val;
if (cur == n) {
break;
}
bool cond0 = cur > 0 && q[cur] != n && p[q[cur] + 1] > cur + 1;
bool cond1 = q[cur + 1] > 1 && p[q[cur + 1] - 1] > cur + 1;
if (cond0 && cond1) {
auto [x, y, z] = sgt1.FindBetterSuffix();
int pos;
if (y < x) {
pos = q[y];
} else {
pos = sgt0.FindFirstGE(q[x], z);
}
if (pos == -1) {
ans[segment_start.size()] = ans[segment_start.size() - 1];
} else {
Flip(pos);
ans[segment_start.size() - 1] = sgt1.d[1].d.hash_val;
Flip(pos);
}
}
if (cond0) {
Flip(q[cur] + 1);
}
if (cond1) {
Flip(q[cur + 1]);
}
}
for (int i = segment_start.size(); i <= n; i++) {
ans[i] = ans[i - 1];
}
for (int i = 1; i <= n; i++) {
cout << ans[i] << ' ';
}
cout << '\n';
}
return 0;
}