• HDU 3183 A Magic Lamp RMQ


    题意:

    给一串不含前导零的(n)个数字,要删去(m(m leq n))个数字,要使剩下的数字最小。

    分析:

    删去(m)个数字就相当于选(n-m)个数字,因为最终选出来的数字的长度是一定的,所以第一个数字越小越好。
    第一个数字只能在区间([1,m+1])中选,否则后面的就不够选了。
    假设我们选在了位置(p),那么第二个数字就在区间([p+1, m+2])中选,以此类推。

    因此RMQ中我们要查询的是最小值的最左下标。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 1000 + 10;
    
    char s[maxn], ans[maxn];
    int n, m;
    
    int d[maxn][11];
    
    int Min(int i, int j) { return s[i] <= s[j] ? i : j; }
    
    void init() {
        for(int i = 0; i < n; i++) d[i][0] = i;
        for(int j = 1; (1 << j) <= n; j++) {
            for(int i = 0; i + (1<<j) - 1 < n; i++) {
                d[i][j] = Min(d[i][j-1], d[i + (1<<(j-1))][j-1]);
            }
        }
    }
    
    int query(int L, int R) {
        int k = 0;
        while((1 << (k+1)) <= R - L + 1) k++;
        return Min(d[L][k], d[R-(1<<k)+1][k]);
    }
    
    int main()
    {
        while(scanf("%s", s) == 1) {
            n = strlen(s);
            scanf("%d", &m);
            init();
    
            int choose = -1;
            for(int i = 0; i < n - m; i++) {
                choose = query(choose + 1, m + i);
                ans[i] = s[choose];
            }
            ans[n - m] = 0;
    
            int st;
            for(st = 0; st < n - m; st++) if(ans[st] > '0') break;
            if(st >= n - m) printf("0
    ");
            else printf("%s
    ", ans + st);
        }
    
        return 0;
    }
    
  • 相关阅读:
    Finding Palindromes POJ
    吉哥系列故事——完美队形II HDU
    Period II FZU
    生日礼物&&Supermarket
    炮兵阵地[状态压缩DP]
    最小表示法 P1368
    Period
    最长异或路径
    Luogu P5490 扫描线
    解方程
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4999271.html
Copyright © 2020-2023  润新知