http://acm.hdu.edu.cn/showproblem.php?pid=3183
178543 4 1000001 1 100001 2 12345 2 54321 2
13 1 0 123 321
rmq 问题:题意很简单,求一行数字中除去其中m个数字,使其组成最小的一个数字 使用rmq解题,设源数字长为n,那么除去m个数字后剩下的还剩n-m个数字,组成最小的数字。 (1)因为剩下n-m个数字,那么在1到m+1位置中最小的那个数字必是结果中的第一个数字i, (2)然后从这个数字i位置的下个位置i+1开始到m+2位置的数字中最小的那个数字必定是 结果中第二个数字,以此类推下去向后找。 (3)为了保证数字最小所以要保证高位最小还要保证数字长度够用~~
这道题虽是RMQ,但是由于不是很理解RMQ,所以就自己用循环的方法实现了0MS过
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <cstdlib> #include <limits> #include <queue> #include <stack> #include <vector> #include <map> using namespace std; typedef long long LL; #define N 1010 #define INF 0x3f3f3f3f #define PI acos (-1.0) #define EPS 1e-8 #define met(a, b) memset (a, b, sizeof (a)) int main () { char str[N], s[N]; int m; while (scanf ("%s %d", str, &m) != EOF) { int len = strlen (str), pos = 0; int k = len-m, j = 0; met (s, 0); while (k) { int minx = INF, Index = 0; for (int i=pos; i<=m; i++) { if (minx > str[i]-'0') { minx = str[i]-'0'; Index = i; } } s[j++] = str[Index]; pos = Index+1; k--; if (m < len-1) m++; } int flag = 0; k = 0;//记录位数,当已经达到m位的时候结束循环 for (int i=0; i<j;) { while (s[i] == '0' && !flag) i++;//处理前导0的情况 s[k++] = s[i]; flag = 1; i++; } s[k] = '\0'; if (s[0] == '\0') s[0] = '0', s[1] = '\0';//处理len==m的情况 puts (s); } return 0; }