题意:对给定m位数删除其中n位,不改变剩余数字排列,求剩余数字组成的最小数。
思路:选m - n个数 RMQ求最小值 t数组求最小值第一次出现的位置 左右区间随之改变
wa了两次 没特判 m = n 的情况 / t数组存了最小值最后一次出现的位置(25行没用小于等于号用了小于号)
1 #include<map> 2 #include<set> 3 #include<cmath> 4 #include<cstdio> 5 #include<vector> 6 #include<cstring> 7 #include<cstdlib> 8 #include<iostream> 9 #include<algorithm> 10 using namespace std; 11 const int N = 20; 12 int n, q, len; 13 int a[1007],b[1007], f[1007][N], t[1007][N]; 14 void RMQ() 15 { 16 for (int i = 1; i <= len; i++) 17 { 18 f[i][0] = a[i]; 19 t[i][0] = i; 20 } 21 for (int j = 1; (1 << j) <= len; j++) 22 { 23 for (int i = 1; i + (1<<j) - 1 <= len; i++) 24 { 25 if(f[i][j - 1] <= f[i + (1 << (j - 1))][j - 1]) 26 { 27 f[i][j] = f[i][j - 1]; 28 t[i][j] = t[i][j - 1]; 29 } 30 else 31 { 32 f[i][j] = f[i + (1 << (j - 1))][j - 1]; 33 t[i][j] = t[i + (1 << (j - 1))][j - 1]; 34 } 35 } 36 } 37 } 38 int main() 39 { 40 string s; 41 while (cin >> s) 42 { 43 cin >> n; 44 len = s.size(); 45 if (n == len) cout << "0" << endl; 46 else 47 { 48 for (int i = 0; i < len; i++) a[i + 1] = s[i] - '0'; 49 RMQ(); 50 int k = len - n; 51 int l = 1, r = len - k + 1; 52 for (int i = 1; i <= k; i++) 53 { 54 int s = 0; 55 while (1 << (s + 1) < (r - l + 1)) s++; 56 if (f[l][s] <= f[r - (1 << s) + 1][s]) 57 { 58 b[i] = f[l][s]; 59 l = t[l][s] + 1; 60 r++; 61 } 62 else 63 { 64 b[i] = f[r - (1 << s) + 1][s]; 65 l = t[r - (1 << s) + 1][s] + 1; 66 r++; 67 } 68 } 69 int i = 1; 70 for (i = 1; i < k; i++) 71 { 72 if (b[i] != 0) break; 73 } 74 for (int j = i; j <= k; j++) cout << b[j]; 75 cout << endl; 76 } 77 78 } 79 80 }