// 题意:从长度为 N 的字符串中删除 M 个字符,使得生成的新串的字典序最小
// 思路:反向构造
1 #include "bits/stdc++.h" 2 using namespace std; 3 const int MAXN = 100010; 4 int n; 5 char ans[MAXN]; 6 int Min[MAXN][20], Max[MAXN][20]; 7 8 // 建st表, ans[MAXN], n读入之后调用 9 void makeRmq() 10 { 11 int i, j, len; 12 for(i = 1; i <= n; ++i) { 13 Min[i][0] = Max[i][0] = i; 14 } 15 16 int p, q; 17 for(j = 1; (len = 1 << j) <= n; ++j) { 18 for(i = 1; i + len - 1 <= n; ++i) { 19 p = Min[i][j - 1]; 20 q = Min[i + (len >> 1)][j - 1]; 21 if(ans[p] < ans[q] || (ans[p] == ans[q] && p < q)) { 22 Min[i][j] = p; 23 } 24 else { 25 Min[i][j] = q; 26 } 27 28 // p = Max[i][j - 1]; 29 // q = Max[i + (len >> 1)][j - 1]; 30 // if(ans[p] > ans[q] || (ans[p] == ans[q] && p < q)) { 31 // Max[i][j] = p; 32 // } 33 // else { 34 // Max[i][j] = q; 35 // } 36 } 37 } 38 } 39 40 // 取 [l, r] 的最小值和最大值放入 minValue 和 maxValue 中,且不需要初始化 minValue 和 maxValue 41 void ask(int l, int r, int &min_pos) 42 { 43 int pow_num, len, p, q; 44 pow_num = int(log(r - l + 1) / log(2)); 45 len = 1 << pow_num; 46 47 p = Min[l][pow_num]; 48 q = Min[r - len + 1][pow_num]; 49 if(ans[p] < ans[q] || (ans[p] == ans[q] && p < q)) { 50 min_pos = p; 51 } 52 else { 53 min_pos = q; 54 } 55 56 // p = Max[l][pow_num]; 57 // q = Max[r - len + 1][pow_num]; 58 // if(ans[p] > ans[q] || (ans[p] == ans[q] && p < q)) { 59 // maxValue = ans[p]; 60 // } 61 // else { 62 // maxValue = ans[q]; 63 // } 64 } 65 char res[1010]; 66 int tot; 67 int m; 68 69 int main() 70 { 71 while (scanf("%s%d", ans + 1, &m) != EOF) { 72 tot = 0; 73 n = strlen(ans + 1); 74 makeRmq(); 75 int cnt = n - m; 76 int min_pos; 77 int l = 1, r = m + 1; 78 while (cnt--) { 79 ask(l, r, min_pos); 80 res[tot++] = ans[min_pos]; 81 l = min_pos + 1; 82 ++r; 83 } 84 res[tot] = ‘\0‘; 85 int index = 0; 86 while(index <= tot - 1 && res[index] == ‘0‘) { 87 ++index; 88 } 89 if(index == tot) { 90 printf("0\n"); 91 continue; 92 } 93 printf("%s\n", res + index); 94 } 95 }
时间: 2024-09-30 06:45:06