水题啊,好不容易遇到会写的1900分

明 显 如 果 在 答 案 中 出 现 了 字 母 x 明显如果在答案中出现了字母x x

那 么 小 于 x 的 字 母 一 定 全 选 , 因 为 这 样 使 得 x 最 靠 后 那么小于x的字母一定全选,因为这样使得x最靠后 x,使x

所 以 我 们 枚 举 这 个 x 字 母 所以我们枚举这个x字母 x

贪 心 的 , 小 于 x 的 全 选 , 等 于 x 的 暂 时 不 选 , 记 录 下 来 贪心的,小于x的全选,等于x的暂时不选,记录下来 ,x,x,

后 续 如 果 不 满 足 m 个 的 话 , 就 贪 心 的 去 前 面 拿 一 个 最 近 的 x 后续如果不满足m个的话,就贪心的去前面拿一个最近的x m,x

代码也非常的短

46ms也蛮快的

#include <bits/stdc++.h>
using namespace std;
int n,m,vis[30],flag;
char a[1000009];
void isok(char w)
{
	//表示本次小于等于w的都去选
	int last=0,nxt=-1;
	for(int i=0;i<=25;i++)	vis[i]=0;
	for(int i=1;i<=n;i++)
	{
		if( a[i]<w )
			vis[ a[i]-'a' ]++,last=i;
		else if( a[i]==w )	nxt=i;//这是w,暂时不选 
		if( i-last>=m )
		{
			if( nxt!=-1&&i-nxt<m )
			{
				vis[w-'a']++,last=nxt;
				continue;
			}
			return;
		}
	} 
	flag=1;
}
int main()
{
	cin >> m >> (a+1);
	n=strlen(a+1);
	for(char i='a';i<='z';i++)
	{
		isok(i);
		if( !flag )	continue;
		for(int i=0;i<=25;i++)
			while( vis[i]-- )	cout << char(i+'a');	
		return 0;
	}
}