http://codeforces.com/contest/733/problem/C
一道很恶心的模拟题。
注意到如果能凑成b[1],那么a的前缀和一定是有一个满足是b[1]的,因为,如果跳过了一些前面的数不用,就会剩下一个多余的东西在哪里。所以就是把a数组分成了若干段,判断每一段是否凑成b[i]了,
能凑成b[i]的条件是:
这一段a[]中,最大值的左边或者右边要有一个比它小,然后吃了它,就能吃全部了。
注意当只有1个的时候,是一定是true的。不用吃其他了,
剩下的就是恶心的模拟了,因为它的下标不断变换。
所以我就用了一个vector去存。
删除vector中的元素要用迭代器。
复杂度是O(n)的,
总体复杂度O(n*n)
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 500 + 20; int a[maxn]; int b[maxn]; int n, k; vector<int>arr; struct node { int pos; char ch; node() {} node(int a, char b) : pos(a), ch(b) {} }show[maxn]; int lenshow; bool slove(int begin, int end, int how) { if (begin == end) return true; int mx = -inf; arr.clear(); for (int i = 1; i <= how; ++i) arr.push_back(inf); for (int i = begin; i <= end; ++i) { mx = max(mx, a[i]); } int pos = inf; for (int i = begin; i <= end; ++i) { if (a[i] == mx) { if (i > begin && mx > a[i - 1]) { pos = i - begin + 1; break; } if (i < end && mx > a[i + 1]) { pos = i - begin + 1; break; } } } if (pos == inf) return false; for (int i = begin; i <= end; ++i) arr.push_back(a[i]); vector<int> :: iterator it = arr.begin() + pos + how - 1; vector<int> :: iterator it2; int all = end - begin + 1; pos = pos + how - 1; int tbegin = how; int tend = arr.size() - 1; while (true) { if (pos > tbegin && arr[pos] > arr[pos - 1]) { show[++lenshow] = node(pos, 'L'); arr[pos - 1] += arr[pos]; it2 = it; arr.erase(it2); it--; // cout << *it << endl; pos--; all--; tend = arr.size() - 1; if (all == 1) return true; } if (pos < tend && arr[pos] > arr[pos + 1]) { show[++lenshow] = node(pos, 'R'); arr[pos + 1] += arr[pos]; it2 = it; arr.erase(it2); // cout << *it << endl; // it = arr.begin() + how + pos - 1; tend = arr.size() - 1; all--; if (all == 1) return true; } } return true; } void work() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } scanf("%d", &k); for (int i = 1; i <= k; ++i) { scanf("%d", &b[i]); } int how = 1; int begin = 1; int up = 0; for (int i = 1; i <= k; ++i) { int total = 0; bool flag = false; int tbegin = begin; while (begin <= n) { total += a[begin]; if (total == b[i]) { flag = slove(tbegin, begin, how); up = begin; how++; begin++; break; } begin++; if (total > b[i]) { printf("NO "); return; } } if (flag == false) { printf("NO "); return; } } if (up != n) { cout << "NO" << endl; return; } cout << "YES" << endl; for (int i = 1; i <= lenshow; ++i) { printf("%d %c ", show[i].pos, show[i].ch); } } int main() { #ifdef local freopen("data.txt","r",stdin); #endif work(); return 0; }