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

猜你喜欢

转载自blog.csdn.net/tomandjake_/article/details/83180490