Task On The Board

题目连接: Task On The Board

大致题意:

给出一个仅含有小写字母的字符串及其长度, 再给出一个n个整数组成的数组(称为a).

希望你构造出一个新的字符串t, 长度为n(数组长度).
需要满足:
①t字符串的字符只能来源于给定串的字符.
②对于t[j] > t[i], 那么a[i] = |i-j|, 相当于对于a[i]而言, 应该是所有比t[i]大的字符t[j]的所有|i-j|累加和.

解题思路:

从0下手, 对于当前a[i]为0的位置一定是构造串t中的最大字母, 则我们只需要从给定串中去寻找最大字母的个数满不满足当前0的个数. 如果满足的话则将这些位置进行标记, 让其余位置进行-=|i-j|, 则我们还会得到一些0的位置, 重复上述操作, 直至所有位置都被标记即可.

AC代码:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
map<int, int> mp;
int a[55], b[55]; 
bool vis[55]; //标记当前位置已经完成
set<int> st; //临时存放当前为0的位置
void init() {
	memset(a, 0, sizeof(a));
	memset(vis, 0, sizeof(vis));
	mp.clear();
}
int main(void)
{
	int t; scanf("%d", &t);
	while (t--) {
		init();
		int n; scanf("%d", &n);
		string s; cin >> s;
		for (auto i : s) { mp[i]++; } //统计s中出现过的字符

		int m; scanf("%d", &m);
		for (int i = 1; i <= m; ++i) {
			scanf("%d", &a[i]);
		}

		int all = 0; //已经规划好位置的字符个数
		while (all < m) {
			int cou = 0; //0的个数
			for (int i = 1; i <= m; ++i) { //统计0的个数
				if (!vis[i] && a[i] == 0) vis[i] = 1, cou++, st.insert(i);
			}
			while (mp.rbegin()->second < cou) mp.erase(--mp.end()); //排除个数不足的字符
			auto temp = mp.rbegin()->first; //符合要求的
			mp.erase(--mp.end());
			for (auto op = st.begin(); op != st.end();) { //更新其余位置的值
				b[*op] = temp;
				for (int i = 1; i <= m; ++i) {
					if (!vis[i]) a[i] -= abs(*op - i);
				}
				st.erase(op++);
			}
			all += cou; //更新操作完的位置数量
		}
		for (int i = 1; i <= m; ++i) {
			printf("%c", b[i]);
		}
		printf("\n");
	}
	return 0;
}

END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值