题解:CF2201A2 Lost Civilization (Hard Version)
C1/C2
题解
Part.1
模拟样例可以发现,最终的序列是多个树形结构。在操作过程中,在
Part.2
画图模拟样例可以发现,若创建一个源点,向每个树根连边,则区间
启示
- 拆贡献
- 画图模拟样例大法好
Code
应该比较简洁了吧。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 3e5 + 5;
ll T, n, cnt, ans;
ll a[N], deep[N], b[N], f[N];
stack<int> stk;
void DFS(int &p, int val, int dep) {
deep[p] = dep;
for (p++; a[p] == val + 1; ) {
DFS(p, val + 1, dep + 1);
}
return ;
}
void Clear() {
cnt = ans = 0;
for (int i = 0; i <= n + 1; i++) {
a[i] = deep[i] = b[i] = f[i] = 0;
}
for (; !stk.empty(); stk.pop()) ;
return ;
}
void Solve() {
Clear();
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
}
for (int p = 1; p <= n; ) {
cnt++;
DFS(p, a[p], 1);
}
for (int i = 1; i <= n; i++) {
for (; !stk.empty() && deep[stk.top()] >= deep[i]; stk.pop()) ;
if (!stk.empty()) {
f[i] = stk.top();
}
stk.push(i);
}
for (int i = 1; i <= n; i++) {
b[f[i] + 1] += n - i + 1;
b[i + 1] -= n - i + 1;
}
for (int i = 1; i <= n; i++) {
b[i] += b[i - 1];
ans += b[i];
}
cout << ans << '\n';
return ;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
for (cin >> T; T--; Solve()) ;
return 0;
}