贪心、扫描线思想
题意
有 \(1-n\) 的一个排列 \(a_i\), 给定 \(b_i\), 满足 \(b_i=\lfloor\frac i{a_i}\rfloor\), 求 \(a_i\) (n <= 5e5)
思路
先解出每一个 \(a_i\) 的取值区间,然后就是经典的作业调度问题
- \(a_i\) 的取值区间
\(b_i=\lfloor\frac i{a_i}\rfloor \Lrarr b_i<=\lfloor\frac i{a_i}\rfloor<b_i+1\)
- 转化为扫描线问题,把区间左端点看作关键时间点,用vector存在 l 时间有哪些 [i, r] 可以加入优先队列(r味关键字的小根堆),然后在从优先队列里取出当前 r 最小的,这个时间点就分配给这个任务
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <cmath>
#include <queue>
using namespace std;
#define endl "\n"
typedef long long ll;
typedef pair<int, int> PII;
const int N = 5e5 + 10;
int n;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--)
{
cin >> n;
vector<vector<PII> > event(n + 1);
for (int i = 1; i <= n; i++)
{
int b;
cin >> b;
int l, r;
if (i % (b + 1) == 0)
l = i / (b + 1) + 1;
else
l = (i + b) / (b + 1);
if (b)
r = i / b;
else
r = n;
event[l].push_back({r, i});
}
vector<int> ans(n + 1);
priority_queue<PII, vector<PII>, greater<PII> > heap;
for (int l = 1; l <= n; l++)
{
for (auto evt : event[l])
heap.push(evt);
auto [r, id] = heap.top();
heap.pop();
ans[id] = l;
}
for (int i = 1; i <= n; i++)
cout << ans[i] << " ";
cout << endl;
}
return 0;
}
标签:vector,int,cin,131,Restoration,Permutation,include
From: https://www.cnblogs.com/hzy717zsy/p/16585350.html