D. Permutation Restoration
time limit per test
4 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Monocarp had a permutation aa of nn integers 11, 22, ..., nn (a permutation is an array where each element from 11 to nn occurs exactly once).
Then Monocarp calculated an array of integers bb of size nn, where bi=⌊iai⌋bi=⌊iai⌋. For example, if the permutation aa is [2,1,4,3][2,1,4,3], then the array bb is equal to [⌊12⌋,⌊21⌋,⌊34⌋,⌊43⌋]=[0,2,0,1][⌊12⌋,⌊21⌋,⌊34⌋,⌊43⌋]=[0,2,0,1].
Unfortunately, the Monocarp has lost his permutation, so he wants to restore it. Your task is to find a permutation aa that corresponds to the given array bb. If there are multiple possible permutations, then print any of them. The tests are constructed in such a way that least one suitable permutation exists.
Input
The first line contains a single integer tt (1≤t≤1051≤t≤105) — number of test cases.
The first line of each test case contains a single integer nn (1≤n≤5⋅1051≤n≤5⋅105).
The second line contains nn integers b1,b2,…,bnb1,b2,…,bn (0≤bi≤n0≤bi≤n).
Additional constrains on the input:
- the sum of nn over test cases does not exceed 5⋅1055⋅105;
- there exists at least one permutation aa that would yield this array bb.
Output
For each test case, print nn integers — a permutation aa that corresponds to the given array bb. If there are multiple possible permutations, then print any of them.
Example
input
Copy
4 4 0 2 0 1 2 1 1 5 0 0 1 4 1 3 0 1 3
output
Copy
2 1 4 3 1 2 3 4 2 1 5 3 2 1
类似贪心的解法。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<map>
#include<queue>
#include<ctime>
#include<algorithm>
#include<iostream>
#include<set>
#include<sstream>
#include<vector>
#include<stack>
#include<deque>
#include<list>
#include<cctype>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<bitset>
#include<numeric>
#include<array>
#include <cassert>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
const int maxdouble = 0x7f;//127
const int mindouble = 0xfe;//254
const ll mod = 1e9 + 7;
//priority_queue
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-')
f=-1;
ch=getchar();
if(ch==-1)
return 0;
}
while(ch>='0'&&ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
inline void write(ll x)
{
if(x<0)
{
putchar('-');
x=-x;
}
if(x>=10)
write(x/10);
putchar(x%10+'0');
}
/*
int prime(ll n)//1不是,需要特判下
{
if(n==0||n==1)
return 0;
for(ll i=2; i*i<=n; i++)
{
if(n % i == 0)
return 0;
}
return 1;
}
*/
ll gcd(ll a,ll b)
{
return b==0 ? a : gcd(b, a%b);
}
ll lcm(ll a, ll b)
{
return a*b/gcd(a, b);
}
inline ll check(ll x) //s*(s+1)=x
{
ll s=sqrt(x*2)+(1e-12);
if((s*(s+1)/2)==x)
return s;
return -1;
}
/*
void getnext()
{
int i = 0, j = -1;
nex[0] = -1;
while(i<m)
{
while(j!=-1&&s[i]!=s[j])
j = nex[j];
nex[++i] = ++j;
}
}
*/
ll ksm(ll a, ll b)
{
ll ret = 1;
while (b)
{
if (b & 1)
ret = ret * a;// % mod;
a = a * a;// % mod;
b >>= 1;
}
return ret;
}
ll ksm1(ll a, ll b, ll p)
{
ll ret = 1;
while (b)
{
if (b & 1)
ret = ret * a % p;
a = a * a % p;
b >>= 1;
}
return ret;
}
ll multi(ll a, ll x, ll MOD)
{
ll ans = 0;
while(x)
{
if(x & 1)
ans = (ans + a) % MOD;
a = (a + a) % MOD;
x >>= 1;
}
return ans;
}
inline ll mul(ll a,ll b,ll mod)
{
return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
}
ll exgcd(ll a, ll b, ll &x, ll &y)//返回的r是a, b的最大公约数
{
if(b==0)
return x = 1, y = 0, a;
ll r = exgcd(b, a%b, x, y);
tie(x, y) = make_tuple(y, x-(a/b)*y);
return r;
}
/*
freopen("triangle.in", "r", stdin);
freopen("triangle.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0);
*/
int lowbit(int x) { return log2((x)&(-x)); }
#define endl '\n'
typedef pair<ll,ll> pii;
const double eps = 1e-5;
const int maxn = 5e5 + 500;
ll l[maxn], r[maxn], a[maxn], b[maxn];
int main(void)
{
int T;
scanf("%d", &T);
while(T--)
{
int n;
scanf("%d", &n);
vector<ll> G[n+1];
for(int i=1; i<=n; i++)
{
scanf("%lld", &b[i]);
if(b[i]==0)
l[i] = i+1, r[i] = n;
else
{
l[i] = i/(b[i]+1)+1;
r[i] = i/b[i];
}
G[l[i]].push_back(i);
}
priority_queue<array<ll,2>, vector<array<ll, 2> >, greater<> > q;
for(int i=1; i<=n; i++)
{
for(auto t:G[i])
q.push({r[t], t});
a[q.top()[1]] = i;
q.pop();
}
for(int i=1; i<=n; i++)
printf("%lld ", a[i]);
cout<<endl;
}
return 0;
}
这篇文章介绍了一种解决Monocarphic问题的方法,通过给定的按地板取整后的数组重建原始排列。博主分享了如何利用贪心策略找出与输入数组对应的排列,适用于1到5万个测试案例的输入限制。
529

被折叠的 条评论
为什么被折叠?



