题意:
一排上有n只怪兽,每个重量为ai,每只怪兽可以吃掉比他重量小的怪兽,并获得这个怪兽的重量,问能否在若干步之后形成k只怪兽,每只重量为bi,如果可以,还需要输出在每一步的状态下,左数第几只怪兽吃掉了它左边还是右边的怪兽。
思路:
仔细观察可以发现,ai的相对顺序没变,所以最后形成的bj一定是由某个连续一段的ai组成,所以对于每个ai都可以知道它最后组成了哪个bj。
这样知道ai与bj的配对关系,我们可以按照b的顺序一个一个处理,假设ai,ai+1,…ak组成了bj,那么显然有一种构造方法,让最大的那个ai逐次吃掉其他的。但是这里需要注意的是最大的可能不止一个,我们找到的最大的必须是可以吃掉左边或者右边的那个。这样模拟一下,下标也一起变化就可以了,具体细节见代码。
另外需要注意的一点就是特判,a的和要等于b的和,而且ai一定要能组成某个bj。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 505;
int a[MAXN], b[MAXN];
vector <int> vec[MAXN];
struct node {
int x;
char c;
};
int main() {
//freopen("in", "r", stdin);
int n, m;
ll suma = 0, sumb = 0;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
suma += (ll)a[i];
}
scanf("%d", &m);
for (int i = 1l; i <= m; i++) {
scanf("%d", &b[i]);
sumb += (ll)b[i];
}
if (suma != sumb) {
puts("NO");
return 0;
}
ll sum = 0, cn = 0;
for (int i = 1; i <= m; i++) {
sum = 0;
while (cn + 1 <= n && sum + a[cn + 1] <= b[i]) {
sum += (ll)a[++cn];
vec[i].push_back(a[cn]);
}
if (sum != b[i]) {
puts("NO");
return 0;
}
}
bool flag = true;
vector <node> ans;
for (int i = 1; i <= m; i++) {
int Max = vec[i][0], cnt = vec[i].size();
if (cnt == 1) continue;
for (int j = 1; j < cnt; j++)
Max = max(Max, vec[i][j]);
bool tag = false;
for (int k = 0; k < cnt; k++) {
if (vec[i][k] != Max) continue;
if (k > 0 && vec[i][k] > vec[i][k - 1]) {
for (int j = k; j > 0; j--)
ans.push_back((node){i - 1 + j + 1, 'L'});
for (int j = k; j < cnt - 1; j++)
ans.push_back((node){i, 'R'});
tag = true;
}
else if (k + 1 < cnt && vec[i][k] > vec[i][k + 1]) {
for (int j = k; j < cnt - 1; j++)
ans.push_back((node){i - 1 + k + 1, 'R'});
for (int j = k; j > 0; j--)
ans.push_back((node){i - 1 + j + 1, 'L'});
tag = true;
}
if (tag) break;
}
if (!tag) {
flag = false;
break;
}
}
if (flag) {
puts("YES");
for (int i = 0; i < (int)ans.size(); i++)
printf("%d %c\n", ans[i].x, ans[i].c);
}
else puts("NO");
return 0;
}