题意:
思路:
代码:
题意:给定长为n的序列a,1<=a[i]<=n,你可以在任意位置插入范围[1,n]的数字,让所有长为k的子段和一致。问是否可以做到,如果可以,输出最终序列。
思路:
代码:
题意:给定一个长为n的字符串,把它的每个字母分到k个小字符串中,问这k个小字符串中字典序最大的字符串 最小是什么样。
贪心策略:
1. 将原字符串按字典序从小到大排序
2. 从前往后k个字母均摊到k个空串中(现在k个字符串每个都包含1个字母)
3. 如果原串只剩一种字母,在 以最小字母开头的字符串中 均摊
4. 否则剩下全部字母加到 最小字母的后面
5. 答案就是第一个字符串和第k个字符串中的较大者
因为要让最大的字符串最小,
如果只剩1种字符,e.g. k=3, ab, ab, b | abb, a, b,要把剩下的一种字符'b'均摊,因为abb大于ab,还要均摊到最小字母的字符串后,因为如果没有这样,会使答案变大
如果剩下不止一种字符,要把剩下的所有字符全加到最小字母后e.g. k=2, abz, ab | abbz, a,因为剩下的最大的那个字符‘z’,要让它在字符串中的位置尽可能靠后,才能使答案最小
//好吧 希望我的逻辑更流畅些。。
代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
int T;
scanf("%d",&T);
while(T--){
int n,k;
scanf("%d%d",&n,&k);
string str;
cin>>str;
sort(str.begin(),str.end());
//以最小字母开头的字符串有cnt个
auto pos=upper_bound(str.begin(),str.end(),str[0]);
int cnt;
if(pos==str.end()) cnt=k;
else cnt=pos-str.begin();
string s1,s2;
s1+=str[0],s2+=str[k-1];//备选答案
if(str[k]!=str[n-1]) { //剩下的字符不止1种
s1+=str.substr(k);
}else{ //只剩一种字符
s1.insert(s1.end(),(n-k+cnt-1)/cnt,str[k]);
//均摊到每个 最小字母开头字符串 的剩下的这一种字符 有 (n-k+cnt-1)/cnt 个//(n-k)/cnt 有余数则+1
}
cout<<max(s1,s2)<<endl;
}
return 0;
}