題意:給出一個初始序列和一個目標序列,讓你對初始序列進行一些合併操作,使得初始序列變成目標序列。
每次操作可以在初始序列中選一個數,然後讓它和相鄰的一個比它小的數合併,合併後的值是這兩個數的和。
分析:很容易想到如果初始序列可以轉換成目標序列,那麼可以根據目標序列將原序列分割,而且這個分割是固定的。如果初始序列有合理的分割方案而且存在合理的合併方案,那麼必定能轉換成目標序列。(每一段的合併的起點可以設爲該段的最大值,當最大值不止一個時,要選一個可以進行合併的最大值作爲起點)
#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;
}