首先不难发现可以从底向上递推,碰到两个相邻的就把上方的点添加进去喵~这样时间和答案成正比喵~但是答案高达 所以会超时喵~
考虑优化这个模拟喵~一层一层向上推,如果原本是个连续区间推一层这个区间长度会短 喵~长度到小男娘
就会删除喵~
所以可以考虑维护一个珂朵莉树喵~额外存储一个当前长度的有序集合,用于删除过短的连续区间喵~可以记录区间长度改变量,这样就不用每次推一层改整个珂朵莉树喵~同时只要维护一个当前段总长度就可以计算答案喵~
但是这样 还是不行喵~考虑加速这个过程,只在存在的层之间推喵~中间统计答案用等差数列求和公式就可以了喵~注意删除时也要统计喵~
时间复杂度 喵~爱你们喵~
#include <algorithm>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
using ll = long long;
int n;
int k;
vector<ll> a;
map<ll, ll> cur;
set<pair<int, ll>> intervals;
int curLevel;
ll sumLen;
ll res;
// n * (n - 1) / 2 + 1 <= x
ll Lf(ll x) {
return x * (x - 1) / 2 + 1;
}
int Level(ll x) {
int l = 1;
int r = n;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (x < Lf(mid)) {
r = mid - 1;
continue;
}
l = mid;
}
return l;
}
void Insert(ll x, int level) {
ll lf = Lf(level);
ll val = x - lf;
auto it = cur.upper_bound(val);
if (it == cur.begin()) {
it = cur.emplace_hint(cur.begin(), val, val + 1 + (n - level));
intervals.emplace(1 + (n - level), val);
sumLen++;
} else {
auto lit = prev(it);
auto& [llf, lrt] = *lit;
ll rt = lrt - (n - level);
if (rt > val) {
return;
}
sumLen++;
if (rt == val) {
intervals.erase({lrt - llf, llf});
lrt++;
intervals.insert({lrt - llf, llf});
it = lit;
} else {
it = cur.emplace_hint(it, val, val + 1 + (n - level));
intervals.emplace(1 + (n - level), val);
}
}
auto rit = next(it);
if (rit != cur.end()) {
auto& [rlf, rrt] = *rit;
if (val + 1 == rlf) {
intervals.erase({rrt - rlf, rlf});
intervals.erase({it->second - it->first, it->first});
it->second = rrt;
intervals.insert({rrt - it->first, it->first});
cur.erase(rit);
}
}
}
void DecreaseLevel(int level) {
while (intervals.size()) {
auto [len, lf] = *intervals.begin();
if (len > n - level) {
break;
}
int lastLen = len - (n - curLevel);
res += (ll)lastLen * (lastLen + 1) / 2;
sumLen -= lastLen;
cur.erase(lf);
intervals.erase(intervals.begin());
}
int diff = curLevel - level;
ll sz = cur.size();
sumLen -= sz * diff;
res += sumLen * diff;
res += sz * ((ll)diff * (diff + 1) / 2);
curLevel = level;
}
void Solve() {
cin >> n >> k;
a.resize(k);
for (auto& x : a) {
cin >> x;
}
sort(a.begin(), a.end(), greater<>());
curLevel = n;
sumLen = 0;
res = 0;
for (const auto& x : a) {
int level = Level(x);
if (level < curLevel) {
DecreaseLevel(level);
}
Insert(x, level);
}
DecreaseLevel(0);
cout << res << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
Solve();
}
}

京公网安备 11010502036488号