RMQ hdu 3183 A Magic Lamp
RMQ hdu 3183 A Magic Lamp
//hdu 3183 A Magic Lamp //RMQ //用RMQ求剩下的n-m个数,第一个数肯定在第一个数和第m+1 个数之间的最小的那个数, //包括第一和m+1,第二个数肯定在上一次求的数到第m+2 个数之间,依次类推 //注意:预处理log时,记得最大下标是所给数的长度,不是2的几次方, //下标就是多少。求最小数时,若有多个和最小值相等的数则去最左的那个, //要不然求下一个最小数时会忽略这些数 #include <stdio.h> #include <string.h> //#include <math.h> #include <algorithm> using namespace std; #define comein freopen("in.txt", "r", stdin); #define comeout freopen("out.txt", "w", stdout); #define N 1005 #define INF 1<<30 #define eps 1e-5 char num[N]; int dp_min[20][N], pos[N]; int lo_2[N]; void RMQ(int len) { for(int i = 1; i <= len; ++i) dp_min[0][i] = i; int index = lo_2[len]; for(int i = 1; i <= index; ++i) { for(int j = 1; j + (1<<i) - 1 <= len; ++j) { if(num[dp_min[i-1][j]] <= num[dp_min[i-1][j + (1<<(i-1)) ]]) dp_min[i][j] = dp_min[i-1][j]; else dp_min[i][j] = dp_min[i-1][j + (1<<(i-1)) ]; } } } int get_min_pos(int from, int to) { int index = lo_2[to - from + 1]; //若有多个和最小值相等的数则去最左的那个,所以这里要取等 if(num[dp_min[index][from]] <= num[dp_min[index][to - (1<<index) + 1]]) return dp_min[index][from]; return dp_min[index][to - (1<<index) + 1]; } int main() { lo_2[0] = -1; for(int i = 1; i < N; ++i) //求2为底的对数 lo_2[i] = i&(i-1) ? lo_2[i-1] : lo_2[i-1] + 1; while(scanf("%s", &num[1]) != EOF) { int del_n, len = strlen(&num[1]); RMQ(len); scanf("%d", &del_n); int left = len - del_n, from = 1, to; to = del_n + 1; while(left) { pos[left-1] = get_min_pos(from, to); from = pos[left-1] + 1; to++; left--; } left = len - del_n; sort(pos, pos + left); int i = 0; while(num[pos[i]] == '0' && i < left) i++; if(i == left) { puts("0"); continue; } for(; i < left; ++i) putchar(num[ pos[i] ]); puts(""); } return 0; }