H - A Magic Lamp HDU - 3183(ST表 + 贪心)

思路

  • 题意
  1. 给我们一个 n<1000 位数让我们删除m位,求当我们删除m位之后剩下的数最小可以是多少?
  • 分析
  1. 首先我们可以对这一的求解的问题进行一个思维转换,题目让求 删除m位之后得到的数最小, 我们可以转换成从n个数字中选择 n-m位(不改变原来数字顺序),组成的数最小,这个转换的一个好处,避免的对 前导零现象 问题的考虑,
  2. 根据贪心可知,在 n-m次的选择步骤中,我们要让每一步选择,都选择当前 选择区间能选择的最小数字(即使最小的数字是0),通过这样的选择之后,这样拼凑出的数字就一定是最小的,
  3. 现在我们怎么找:“当前选择区间能选择的最小数字”, 这就用到了 ST表 来维护最小每个区间的最最小值,这样我们就能快速的找到 某个区间 的最小数字了
  4. 不过 我们这里的 ST表中 存储的是下标,但是比较的时候 是根据下标处的元素的值的大小来判断大小的

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
/* #include <unordered_map> */
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define pr printf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
using namespace std;

const int mxn = 1005;
char s[mxn];
char res[mxn];
int f[mxn][20];
int Min(int i, int j)
{
    if(s[i] <= s[j])
        return i;
    return j;
}

void ST(int n)
{
    for_(i, 0, n - 1) f[i][0] = i;

    for(int j = 1; (1 << j) <= n; j ++)
        for(int i = 0; i + (1 << j) - 1 < n; i ++)
            f[i][j] = Min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}

int get_min(int l, int r)
{
    int k = 0;
    while(1 << (k + 1) <= r - l + 1) k ++;
    return Min(f[l][k], f[r - (1 << k) + 1][k]);
}

int main()
{
    /* fre(); */
    int m;
    while(sc("%s %d", s, &m) != EOF)
    {
        int n = strlen(s);
        ST(n);
        int i = 0, cnt = 0, len = n - m;
        while(len --)
        {
            i = get_min(i, n - len - 1);
            res[cnt ++] = s[i ++];
        }
        res[cnt] = '\0';

        int lead = 0;       //前导零
        while(res[lead] == '0' && lead < cnt) lead ++;

        if(lead == cnt)
            pr("0\n");
        else
            pr("%s\n", res + lead);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/107531797