题解:P15652 [省选联考 2026] 排列游戏 / perm
Wyh_dailyAC · · 题解
题意
略。
Sol
排列的区间
求前缀
没有记载到跳变的位置就在维持前缀 / 后缀
总时间复杂度
注:求前 / 后缀
Code
#include "perm.h"
#include <bits/stdc++.h>
using namespace std;
int C, T;
void init(int c, int t) { C = c, T = t; }
vector<int> perm(int n) {
vector<int> ans(n, -1);
if (n == 1) { ans[0] = 0; return ans; }
int pP = n, pos0 = -1;
for (int i = 1; i < n; i++) {
int pm = query(i, n - 1);
if (pm < pP) {
ans[i - 1] = pm;
if (pm == 0) { pos0 = i - 1; break; }
}
pP = pm;
}
if (pos0 == -1) { ans[n - 1] = 0; pos0 = n - 1; }
int sP = n;
for (int j = n - 1; j > pos0; j--) {
int sm = query(0, j - 1);
if (sm < sP) {
if (ans[j] == -1) ans[j] = sm;
}
sP = sm;
}
vector<int> vpos(n, -1);
for (int i = 0; i < n; i++) if (ans[i] != -1) vpos[ans[i]] = i;
set<int> emp;
for (int i = 0; i < n; i++) if (ans[i] == -1) emp.insert(i);
int L = vpos[0], R = vpos[0];
for (int v = 0; v < n; v++) {
if (vpos[v] != -1) {
L = min(L, vpos[v]);
R = max(R, vpos[v]);
} else {
auto it = emp.lower_bound(L);
int pos = *it;
ans[pos] = v;
vpos[v] = pos;
emp.erase(it);
}
}
return ans;
}