考 虑 b i = 0 的 特 殊 点 考虑b_i=0的特殊点 考虑bi=0的特殊点
b i = 0 的 点 一 定 是 当 前 字 母 最 大 的 , 否 则 会 和 更 大 的 字 母 产 生 贡 献 b_i=0的点一定是当前字母最大的,否则会和更大的字母产生贡献 bi=0的点一定是当前字母最大的,否则会和更大的字母产生贡献
所 以 第 一 步 , 用 最 大 且 足 够 数 目 的 字 母 去 填 充 所 有 b i = 0 , 标 记 填 过 所以第一步,用最大且足够数目的字母去填充所有b_i=0,标记填过 所以第一步,用最大且足够数目的字母去填充所有bi=0,标记填过
那 么 其 余 没 填 过 的 都 比 这 些 字 母 小 , 所 以 对 其 余 的 b i 修 改 那么其余没填过的都比这些字母小,所以对其余的b_i修改 那么其余没填过的都比这些字母小,所以对其余的bi修改
怎 么 修 改 ? 比 如 b i = 0 且 没 被 标 记 的 点 位 置 是 n u m 怎么修改?比如b_i=0且没被标记的点位置是num 怎么修改?比如bi=0且没被标记的点位置是num
那 么 对 于 所 有 的 b j ! = 0 , b j = b j − a b s ( n u m − j ) , 也 就 是 减 掉 n u m 对 j 的 影 响 那么对于所有的b_j!=0,b_j=b_j-abs(num-j),也就是减掉num对j的影响 那么对于所有的bj!=0,bj=bj−abs(num−j),也就是减掉num对j的影响
修 改 后 , 又 有 一 些 没 标 记 的 b i 变 成 0 , 那 么 这 些 点 是 余 下 点 中 最 大 的 修改后,又有一些没标记的b_i变成0,那么这些点是余下点中最大的 修改后,又有一些没标记的bi变成0,那么这些点是余下点中最大的
重 复 上 面 的 步 骤 即 可 完 成 步 骤 重复上面的步骤即可完成步骤 重复上面的步骤即可完成步骤
#include <bits/stdc++.h>
using namespace std;
const int maxn=1299;
char a[maxn],ans[maxn];
int shu[27],vis[maxn],m,b[maxn];
int main()
{
int t,n;
cin>>t;
while(t--)
{
memset(shu,0,sizeof(shu));
cin>>(a+1)>>m;
for(int i=1;i<=m;i++) cin>>b[i];
for(int i=1;i<=strlen(a+1);i++)
shu[a[i]-'a'+1]++;
int num=26,da=0;
while(1)
{
int zero=0,k;
for(int i=1;i<=m;i++)
if(b[i]==0&&vis[i]==0) zero++;
for(int i=num;i>=1;i--)
if(shu[i]>=zero)
{ k=i;break;}
int cc=0,he=0;
for(int i=1;i<=m;i++)
{
if(b[i]==0&&vis[i]==0)//当前最大的字母
{
vis[i]=1;da++;
ans[i]=char(k+'a'-1);
for(int j=1;j<i;j++)
if(b[j]) b[j]-=(i-j);//减去i字母后面的影响
cc++,he+=i;
}
else if(b[i])
b[i]=b[i]-(cc*i-he);//减去i字母前面的影响
}
num=k-1;//找下一个字母
if(da==m) break;
}
for(int i=1;i<=m;i++) cout<<ans[i];
cout<<endl;
for(int i=1;i<=m;i++) vis[i]=0;
}
}