HDU3183 贪心/RMQ-ST表

时间:2023-03-09 05:30:28
HDU3183 贪心/RMQ-ST表

A Magic Lamp

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6244    Accepted Submission(s): 2539

Problem Description
Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams. 
The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?
Input
There are several test cases.
Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.
Output
For each case, output the minimum result you can get in one line.
If the result contains leading zero, ignore it. 
Sample Input
178543 4
1000001 1
100001 2
12345 2
54321 2
Sample Output
13
1
123
321
这个题题意很简单,就是给你一个长度为n的数,要求从中去掉m位,剩余位顺序不变,求能得到的最小的数
其中允许得到有前导零的数
用贪心做的话就很简单,通过观察我们可以得到一个结论
最终答案的第一位一定在下标为0~m之间 如果不是这样的话我们就无法凑出n-m位的数了
同理,第二位一定在上一位的下标+1到m+1之间
代码也很简单:
 #include <algorithm>
#include <iostream>
#include <cstring>
using namespace std; int main()
{
ios::sync_with_stdio(false);
int m;
char str[];
while (cin >> str >> m)
{
int len = strlen(str);
if (len <= m)
{
cout << "" << endl;
continue;
} int flag = ;
int n = len;
int l = , r = m;
for (int i = ; i < n - m; i++)
{
char min = str[l];
int pos = l;
for (int j = l; j <= r; j++)
{
if (str[j]< min)
{
min = str[j];
pos = j;
}
}
l = pos + ;
r++;
if (!flag && min == '')
continue;
cout << min;
flag++;
} if (!flag)
cout << ;
cout << endl;
} return ;
}

用st表的话也差不多是一个思路,我们先用st表处理得到各个区间最小的数的下标,然后同样按照贪心去求0~m,pos+1~m+1,pos+1~m+2.......

 #include <iostream>
#include <cmath>
#include <string> using namespace std; string s;
int n;
int st[][];
char ans[]; int Min(int a, int b)
{
return s[a] <= s[b] ? a : b;
} void init()
{
for (int i = ; i < s.size(); i++)
st[i][] = i; for (int j = ; ( << j) < s.size(); j++)
for (int i = ; i + ( << j) - < s.size(); i++)
{
st[i][j] = Min(st[i][j - ], st[i + ( << (j - ))][j - ]);
//cout << i << ends << j << endl;
}
} int search(int l, int r)
{
int k = (int)(log((double)(r - l + )) / log(2.0));
return Min(st[l][k], st[r - ( << k) + ][k]);
} int main()
{
ios::sync_with_stdio(false);
while (cin >> s >> n)
{
init();
int len = s.size() - n;
int pos = ;
int flag = ;
while (len--)
{
pos = search(pos,n + flag);
ans[flag++] = s[pos];
//cout << s[pos] << endl;
pos++;
} flag = ; for (int i = ; i < s.size() - n; i++)
{
if (!flag && ans[i] == '')
continue;
flag++;
cout << ans[i];
}
if (!flag)
cout << ;
cout << endl;
} return ;
}