题意:给出一个初始序列和一个目标序列,让你对初始序列进行一些合并操作,使得初始序列变成目标序列。
每次操作可以在初始序列中选一个数,然后让它和相邻的一个比它小的数合并,合并后的值是这两个数的和。
分析:很容易想到如果初始序列可以转换成目标序列,那么可以根据目标序列将原序列分割,而且这个分割是固定的。如果初始序列有合理的分割方案而且存在合理的合并方案,那么必定能转换成目标序列。(每一段的合并的起点可以设为该段的最大值,当最大值不止一个时,要选一个可以进行合并的最大值作为起点)
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l, r, m;
node() {}
node(int _l, int _r, int _m):l(_l),r(_r),m(_m) { }
};
int a[600], b[600];
vector<node>v;
int main()
{
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
int m;
scanf("%d", &m);
for(int j = 1; j <= m; j++)
{
scanf("%d", &b[j]);
}
int cnt = 0;
int flag = 1, i, j, k = 1, index = 0;
for(i = 1, j = 1; i <= n; i++)
{
cnt += a[i];
if(j == m + 1)
{
flag = 0;
break;
}
if(a[i] > a[index]) index = i;
if(cnt == b[j])
{
if(index != k || i ==k);
else
{
int tr = index + 1;
while(tr <= i && a[index] == a[tr]) tr++;
if(tr > i)
{
flag = 0;
break;
}
index = tr - 1;
} // index为每一段进行合并的起点
v.push_back(node(k, i, index));
index = 0;
cnt = 0;
j++;
k = i + 1;
}
else if(cnt > b[j])
{
flag = 0;
break;
}
}
if(j != m + 1)
flag = 0;
if(!flag) puts("NO");
else
{
puts("YES");
int cnt = 0;
for(int i = 0; i < v.size(); i++)
{
if(a[v[i].m] > a[v[i].m + 1])
{
int tmp = v[i].m - cnt;
for(int j = v[i].m; j < v[i].r; j++)
{
printf("%d R\n", tmp);
cnt++;
}
int tp=tmp;
for(int j = v[i].m; j > v[i].l; j--)
{
printf("%d L\n", tp);
cnt++;
tp--;
}
}
else
{
for(int j = v[i].m; j > v[i].l; j--)
{
printf("%d L\n", v[i].m - cnt);
cnt++;
}
int tmp = v[i].m - cnt;
for(int j = v[i].m; j < v[i].r; j++)
{
printf("%d R\n", tmp);
cnt++;
}
}
}
}
return 0;
}