2019 计蒜之道 复赛 - D. “星云系统”

VIPKID 是在线少儿英语教育平台,网络稳定是在线教育课程质量的红线,VIPKID 为此推出了全球最稳定的教育网络系统 —— “星云系统”。星云系统目前建立了覆盖全球 3535 个国家的 55 条核心跨海专线,在 1616 个国家的 5555 个城市建立了中心传输节点,具备一分钟内自由切换路由的能力,确保了全球跨洋课堂的高清音、视频通信,为流畅的课堂体验打下坚实基础。

全世界的中心传输节点和各地的网络节点组成的这个“星云系统”,何其复杂。我们现在只考虑一条支线上的网络节点,每一个网络节点比作一个字符的话,这条支线就是一个字符串。

现在给定你一个字符串 ss 以及一个整数 kk,请求出 ss 的字典序最小的长度为 kk 的子序列。

输入格式

第一行一个由小写英文字母构成的字符串 ss,第二行一个正整数 kk。

输出格式

一行一个字符串 ans,表示答案。

数据规模

0<k≤∣s∣≤5000000

样例输入

helloworld
5

样例输出

ellld

解法有点贪心的思想,每次选出“可取区间”内的最小字符,选k次就好了。假设字符串为"helloworld", k =  5,为了保证选取的子序列长度为5,那么第一次可取的区间[0,5],也就是说即使在极端情况下选了index=5这个位置上的字符,这样也能保证取满5个字符,接下来的事情就是重复上一步的步骤了, 每取完第i个字符后,剩下的字符应该至少在当前选中位置pos的下一位开始找。容易得到“可取区间”上边界为pos + 1, 下边界为∣s∣ - (k - (i + 1))。

事实上即使这样还是超时,学弟考虑了测试数据的一种极端情况:全由‘a’组成的长字符串,于是就有了第16行的优化。

#include<iostream>
#include<cstring>
#include<cstdio> 
using namespace std;
const int maxn = 5e6 + 10;
char out[maxn], str[maxn];
int main() {
  int k;
  scanf("%s", str);
  scanf("%d", &k);
  int len = strlen(str);
  int l = 0, r = len - k, pos = 0;
  for (int i = 0; i < k; i++) {
    char min_ch = 'z' + 1;
    for (int j = l; j <= r; j++) {
      if (str[j] == 'a') {
        min_ch = 'a';
        pos = j;
        break;
      } else {
        if (str[j] < min_ch) {
          min_ch = str[j];
          pos = j;
        }
      }
    }
    l = pos + 1, r = len - (k - (i + 1));
    out[i] = min_ch;
  }
  printf("%s", out);
  return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值