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;
}

posted @ 2022-07-09 14:51  OIer某罗  阅读(12)  评论(0编辑  收藏  举报