题解:CF2239C Revival
这很神秘你知道吗。难点在于想到倒着做。
显然
\[s_i-s_{i-1}=\sum_{j=1}^{i-1}[p_j>p_i]
\]
也就是说,\(s_i-s_{i-1}\) 传达的信息是 \(p_i\) 在 \(p_{1\sim i}\) 中的排名。
容易想到逐个确定 \(s_i\) 对应位置的值。
如果从左到右做,我们只知道 \(p_{1\sim i-1}\) 对应的值;但是如果从右到左做,确定了 \(p_{i+1\sim n}\) 的值后,\(p_{1\sim i}\) 的值构成的集合就可以确定了。
于是考虑从右到左做。设当前一对相邻的位置为 \(s_l\) 和 \(s_r\),\(p_{l+1\sim r-1}\) 和 \(p_{r+1\sim n}\) 中的值都已经确定了,此时可以确定 \(p_{1\sim r}\) 中值构成的集合 \(S\)。分离贡献:
\[\begin{align*}
s_r-s_l&=\sum_{i=l+1}^{r-1}\sum_{j=i+1}^{r-1}[p_i>p_j]+\sum_{i=l+1}^{r-1}\sum_{x\in S}[x>p_i]-\frac{(r-l-1)(r-l-2)}{2}\\
&+\sum_{x\in S}[x>p_r]-\sum_{i=l+1}^{r-1}[p_i<p_r]
\end{align*}
\]
与 \(p_r\) 无关的部分是定值 \(C\)。设
\[f(v)=\sum_{x\in S}[x>v]-\sum_{i=l+1}^{r-1}[p_i<v]
\]
不妨限制定义域为 \(S\),则任取 \(v_1,v_2\in S\ (v_1<v_2)\) 做差:
\[f(v_1)-f(v_2)=\sum_{x\in S}[v_1<x\leq v_2]+\sum_{i=l+1}^{r-1}[v_1\leq p_i<v_2]
\]
显然上式 \(>0\),因此 \(f\) 在 \(S\) 上严格单调递减。类似地,不难得出 \(f\) 在 \([n]\) 上单调不增。由于题目保证有解,我们二分出最小的 \(x\) 使得 \(f(x)\leq s_r-s_l-C\),取 \(p_r=x\) 即可。
开两棵树状数组分别维护 \(p_{l+1\sim r-1}\) 和 \(S\) 即可。时间复杂度为 \(\mathcal{O}(n\log^2{n})\)。
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using i128 = __int128;
using ui = unsigned int;
using ull = unsigned long long;
using u128 = unsigned __int128;
using ld = long double;
using pii = pair<int, int>;
const int MAXN = 2e5 + 5;
template<typename T> T lowbit(T x) { return x & -x; }
template<typename T> void chkMin(T &x, T y) { x = y < x ? y : x; }
template<typename T> void chkMax(T &x, T y) { x = x < y ? y : x; }
constexpr int lg2(ll x) { return 63 ^ __builtin_clzll(x); }
constexpr ll bitCeil(ll x) { return x == 1 ? 1ll : 1ll << lg2(x - 1) + 1; }
int tc, n;
ll a[MAXN];
bool tp[MAXN];
struct BIT {
int c[MAXN];
void init(int n) {
fill(c + 1, c + n + 1, 0);
}
int query(int x) {
int res = 0;
for (; x; x -= lowbit(x)) res += c[x];
return res;
}
void add(int x, int v) {
for (; x <= n; x += lowbit(x)) c[x] += v;
}
} ft1, ft2;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> tc;
while (tc--) {
cin >> n;
for (int i = 1; i <= n; ++i) {
string s;
cin >> s >> a[i];
tp[i] = s[0] == 's';
}
vector<int> pos;
for (int i = n; i; --i)
if (tp[i])
pos.emplace_back(i);
pos.emplace_back(0);
ft1.init(n);
ft2.init(n);
for (int i = 1; i <= n; ++i) ft1.add(i, 1);
for (int i = n; i > pos[0]; --i) ft1.add(a[i], -1);
for (int i = 0; i < pos.size() - 1; ++i) {
int l = pos[i + 1], r = pos[i];
ll val = 0;
for (int j = r - 1; j >= l + 1; --j) {
val += ft2.query(a[j] - 1);
ft2.add(a[j], 1);
}
for (int j = l + 1; j <= r - 1; ++j) val += ft1.query(n) - ft1.query(a[j]);
val -= (ll)(r - l - 1) * (r - l - 2) >> 1;
val = a[r] - a[l] - val;
int L = 1, R = n;
while (L < R) {
int mid = L + R >> 1;
ll v = ft1.query(n) - ft1.query(mid) - ft2.query(mid - 1);
if (v <= val) R = mid;
else L = mid + 1;
}
a[r] = L;
ft1.add(a[r], -1);
for (int j = l + 1; j <= r - 1; ++j) {
ft1.add(a[j], -1);
ft2.add(a[j], -1);
}
}
for (int i = 1; i <= n; ++i) cout << a[i] << " \n"[i == n];
}
return 0;
}

浙公网安备 33010602011771号