Problem - 1701D - Codeforces
题意:
思路:
手推样例可知:
一开始想的是,把这些区间按右端点排序,然根据排序后的贪心
事实上不是这样的,而是要把有可能的区间扔进堆里:
感觉这种带堆的贪心,都是取当前所有可行解中的最优解
Code:
#include <bits/stdc++.h>
#define int long long
using i64 = long long;
constexpr int N = 5e5 + 10;
constexpr int mod = 998244353;
std::vector<std::array<int,3> > V;
std::priority_queue<std::array<int,2>, std::vector<std::array<int,2> >, std::greater<std::array<int,2 > > > q;
int n;
int a[N], b[N], vis[N], ans[N];
bool cmp(std::array<int,3> x, std::array<int,3> y) {
if (x[0] == y[0]) return x[1] < y[1];
return x[0] < y[0];
}
bool check(int x, int l, int r) {
return x >= l && x <= r;
}
void solve() {
std::cin >> n;
V.clear();
while(!q.empty()) q.pop();
for (int i = 1; i <= n; i ++) {
vis[i] = 0;
}
for (int i = 1; i <= n; i ++) {
std::cin >> b[i];
}
for (int i = 1; i <= n; i ++) {
int l = i / (b[i] + 1) + 1;
int r;
if (b[i] == 0) r = n;
else r = i / b[i];
V.push_back({l, r, i});
}
std::sort(V.begin(), V.end(), cmp);
/*for (int i = 0; i < V.size(); i ++) {
std::cout << V[i][0] << " " << V[i][1] << "\n";
}*/
int idx = 0;
for (int i = 1; i <= n; i ++) {
while(idx < V.size() && V[idx][0] == i) {
q.push({V[idx][1], V[idx][2]});
idx ++;
}
if (q.empty()) continue;
auto [r, id] = q.top();
q.pop();
ans[id] = i;
}
for (int i = 1; i <= n; i ++) {
std::cout << ans[i] << " \n" [i == n];
}
}
signed main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t = 1;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}