Description:
有一个长度为n的整数序列,Li表示在第i个数的左边有多少个数比它大,Ri表式在第i个数的右边有多少个数比它大
(li is the number of indices j (1≤j<i), such that ai<aj and ri is the number of indices j (i<j≤n), such that ai<aj.)
要求构造出一个这样的序列。
Input:
n
Li (1<=i<=n)
Ri(1<=i<=n)
Output:
长度n的整数序列
Analysis:
问题的关键是要找到一个数列中各个数的排序。考虑LI,RI都为0的位置,那个一定是当前最大数,于是可以将那个数从序列中删去,并且将它带来的“影响”也要同时去掉,即将其左边的Ri都减一,右边的Li都减1.于是问题就缩小了一个规模,即从确定n个数的排序,变为确定n-1个数的排序,算法单调性确定。只要依此递推下去,每次都找出当前考虑的最大的数的位置,并且减小问题规模最后就能得到答案。
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<sstream>
#include<cmath>
#include<iterator>
#include<bitset>
#include<stdio.h>
#include<unordered_set>
#include<ctime>
#include<float.h>
using namespace std;
#define _for(i,a,b) for(int i=(a);i<(b);++i)
#define _rep(i,a,b) for(int i=(a);i<=(b);++i)
typedef long long LL;
const int INF = 1 << 30;
const int MOD = 998244353;
const int maxn = 1005;
int n;
int L[maxn], R[maxn];
int vis[maxn],val[maxn];
int main() {
scanf("%d", &n);
_for(i, 0, n) scanf("%d", &L[i]);
_for(i, 0, n) scanf("%d", &R[i]);
int now = n;
while (true) {
bool find = false;
vector<int> idx;
for (int i = 0; i < n; ++i) {
if (!vis[i]&&L[i] == 0 && R[i] == 0) {
idx.push_back(i);
vis[i] = 1;
find = true;
val[i] = now;
}
}
if (!find)break;
now--;
for (auto p : idx) {
for (int i = 0; i < p; ++i)R[i]--;
for (int i = p; i < n; ++i)L[i]--;
}
}
bool ok = true;
for (int i = 0; i < n; ++i)if (!vis[i]) { ok = false; break; }
if (ok) {
puts("YES");
for (int i = 0; i < n; ++i)printf("%d ", val[i]);
printf("\n");
}
else puts("NO");
return 0;
}