[codeforces724D]Dense Subsequence
试题描述
You are given a string s, consisting of lowercase English letters, and the integer m.
One should choose some symbols from the given string so that any contiguous subsegment of length m has at least one selected symbol. Note that here we choose positions of symbols, not the symbols themselves.
Then one uses the chosen symbols to form a new string. All symbols from the chosen position should be used, but we are allowed to rearrange them in any order.
Formally, we choose a subsequence of indices 1 ≤ i_1 < i_2 < ... < i_t ≤ |s|. The selected sequence must meet the following condition: for every j such that 1 ≤ j ≤ |s| - m + 1, there must be at least one selected index that belongs to the segment [j, j + m - 1], i.e. there should exist a k from 1 to t, such that j ≤ i_k ≤ j + m - 1.
Then we take any permutation p of the selected indices and form a new string si_p1si_p2... si_pt.
Find the lexicographically smallest string, that can be obtained using this procedure.
输入
The first line of the input contains a single integer m (1 ≤ m ≤ 100 000).
The second line contains the string s consisting of lowercase English letters. It is guaranteed that this string is non-empty and its length doesn't exceed 100 000. It is also guaranteed that the number m doesn't exceed the length of the string s.
输出
Print the single line containing the lexicographically smallest string, that can be obtained using the procedure described above.
输入示例
3 bcabcbaccba
输出示例
aaabb
数据规模及约定
见“输入”
题解
贪心贪心使劲贪。。。先暴力求一下必须要用到哪些字母,然后除掉最后一个字母,再用个堆和滑动窗口从左往右扫一遍,贪心地取刚才除掉的那个字母。
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <stack> #include <vector> #include <queue> #include <cstring> #include <string> #include <map> #include <set> using namespace std; int read() { int x = 0, f = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); } return x * f; } #define maxn 100010 struct Node { char ch; int pos; Node() {} Node(char _, int __): ch(_), pos(__) {} bool operator < (const Node& t) const { return ch != t.ch ? ch > t.ch : pos < t.pos; } bool operator == (const Node& t) const { return ch == t.ch && pos == t.pos; } } ; priority_queue <Node> Q, delQ; char S[maxn], ans[maxn]; int cnt, n, m; bool vis[maxn]; void solve() { for(char ch = 'a'; ch <= 'z'; ch++) { for(int i = 1; i <= n; i++) if(S[i] == ch) vis[i] = 1, ans[++cnt] = ch; int lstp = 0; bool ok = 1; for(int i = 1; i <= n; i++) { if(vis[i]) lstp = i; if(i - lstp == m){ ok = 0; break; } } if(ok) { for(int i = 1; i <= n; i++) if(S[i] == ch) vis[i] = 0, cnt--; break; } } return ; } int main() { m = read(); scanf("%s", S + 1); n = strlen(S + 1); solve(); int lstp = 0; for(int i = 1; i < m; i++) if(vis[i]) lstp = i; else Q.push(Node(S[i], i)); for(int i = m; i <= n; i++) { if(!vis[i]) Q.push(Node(S[i], i)); else lstp = i; // printf("get: %d %d ", i, lstp); if(i - lstp == m) { Node u = Q.top(); Q.pop(); while(!delQ.empty() && u == delQ.top()) delQ.pop(), u = Q.top(), Q.pop(); ans[++cnt] = u.ch; lstp = u.pos; // printf("set: %d ", lstp); } if(i > m && !vis[i-m]) delQ.push(Node(S[i-m], i - m)); } sort(ans + 1, ans + cnt + 1); ans[cnt+1] = 0; printf("%s ", ans + 1); return 0; }