Codeforces Educational Round 131
D
给定一个 \(n\) 个整数的排列 $ a $。计算一个大小为 \(n\) 的数组 \(b\) 如下: $ b_i = \left\lfloor \frac{i}{a_i} \right\rfloor $ .
给定 \(b\) 数组,还原出一种可能的 \(a\) 数组。
分析: $ b_i = \left\lfloor \frac{i}{a_i} \right\rfloor \leftrightarrow \cfrac{i+1}{b_i+1} \le a_i \le \cfrac{i}{b_i}$。问题转化为:给定一些区间,给它们分别赋上区间内一个值,使得这些值不重复。我们区间贪心:
对区间右端点排序,遍历一遍,每次赋值尽量靠近左端点的值。
#include<bits/stdc++.h>
using namespace std;
#define f(i, a, b) for(int i = (a); i <= (b); i++)
#define cl(i, n) i.clear(),i.resize(n);
#define endl '\n'
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 1e9;
int n;
vector<int> b;
vector<int> ans;
struct qj {
int l, r; int ind;
}q[500010];
bool cmp(qj a, qj b) {
if(a.r != b.r) return a.r < b.r;
else return a.l < b.l;
}
set<int> lef;
int main() {
ios::sync_with_stdio(0);
cin.tie(NULL);
cout.tie(NULL);
int t; cin >> t;
while(t--) {
cin >> n; cl(b, n + 10); cl(ans, n + 10);
lef.clear();
f(i, 1, n) lef.insert(i);
f(i, 1, n) cin >> b[i];
f(i ,1, n) {
q[i].l = (int)ceil((i + 1) * 1.0/ (b[i] + 1));
if(b[i] == 0) q[i].r = n; else q[i].r = (int)floor((i) * 1.0/ (b[i]));
q[i].ind = i;
}
sort(q + 1, q + n + 1, cmp);
f(i, 1, n) {
ans[q[i].ind] = *lef.lower_bound(q[i].l);
lef.erase(ans[q[i].ind]);
}
f(i,1, n) cout << ans[i] << " \n"[i == n];
}
return 0;
}