zoukankan      html  css  js  c++  java
  • HUTXXXX 数字游戏 求解区间的最值

    这题用也算是贪心吧,不过这里有一点数学思想。

    对于要取掉K位的N位数,那么我们留下来的就是N-K位,我们不妨设 T = N - K; 那么我们选择的第一位数的后面就一定要有T-1个数让我们来选,因此第一个数的选择范围就是
    [1, N-T+1],当我们选取了第一个数后(假设位置为P),我们第二个数的选择范围就是 [P+1, N-T-2]了,一次类推。由于我们要取的是最大的数,所以我们每次都选取区间内
    的最大值,用线段树来作优化就可以了。

    代码如下:

    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    using namespace std;
    
    int N, K, leave;
    
    char s[500005];
    
    struct Node
    {
        int l, r, pos, max;
    }e[2000005];
    
    vector<int>v;
    
    void push_up(int p)
    {
        if (e[p<<1].max >= e[p<<1|1].max) {
            e[p].max = e[p<<1].max;
            e[p].pos = e[p<<1].pos;
        }
        else {
            e[p].max = e[p<<1|1].max;
            e[p].pos = e[p<<1|1].pos;
        }
    }
    
    void build(int p, int l, int r)
    { 
        e[p].l = l, e[p].r = r;
        if (l != r) {
            int mid = (l + r) >> 1;
            build(p<<1, l, mid);
            build(p<<1|1, mid+1, r);
            push_up(p);
        }
        else {
            e[p].pos = l, e[p].max = s[l] - '0';
            // 初始化
        }
    }
    
    void query(int p, int l, int r, int &rec, int &pos)
    {
        if (l == e[p].l && r == e[p].r) {
            if (rec != e[p].max) {
                if (rec < e[p].max) {
                    rec = e[p].max;
                    pos = e[p].pos;
                }
            }
            else if (e[p].pos < pos){
                pos = e[p].pos;
            }
            return;
        }
        int mid = (e[p].l + e[p].r) >> 1;
        if (r <= mid) {
            return query(p<<1, l, r, rec, pos);
        }
        else if (l > mid) {
            return query(p<<1|1, l, r, rec, pos);
        }
        else { 
            query(p<<1, l, mid, rec, pos);
            query(p<<1|1, mid+1, r, rec, pos);
        }
    }
    
    int main()
    {
        int pos, rec;
        while (scanf("%d %d", &N, &K) == 2) {
            v.clear();
            pos = 0;
            scanf("%s", s + 1); // 从一开始
            build(1, 1, N);
            leave = N - K; // 剩余的要删除的位数
            while (leave) {  // 如果还有位数需要选择
                rec = -1;
                query(1, pos+1, N-leave+1, rec, pos);
                v.push_back(rec);
                --leave;
            }
            for (int i = 0; i != (int)v.size(); ++i) {
                printf("%d", v[i]);
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    k8s-istio记录
    k8s
    单词 -(动物)
    RxJs
    .netcore 3.1 unbuntu
    单词规整
    AutoMapper
    时间
    ye
    特殊权限
  • 原文地址:https://www.cnblogs.com/Lyush/p/2605808.html
Copyright © 2011-2022 走看看