1. 程式人生 > >Codeforces Mail.Ru Cup 2018 Round 1 C. Candies Distribution(構造)

Codeforces Mail.Ru Cup 2018 Round 1 C. Candies Distribution(構造)

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