Codeforces Mail.Ru Cup 2018 Round 1 C. Candies Distribution(構造)
阿新 • • 發佈:2018-12-16
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; }