zoukankan      html  css  js  c++  java
  • 2019牛客多校第7场 C: Governing sand

    题意:

    题意大概就是要求是一种高度的树超过一半所需要的花费是多少
    

    思路:

    我的思路是做一个前缀和,然后每次枚举一个高度,计算出对应的值
    求砍掉比他高的树的时候,就是做一个前缀和,如果是要求砍掉比他小的树的最小价值
    那么我们可以按照权值做一颗线段树,那么查询前k小的和即可
    然后将两个权值加起来保存最小的值
    

    附上代码:

    #include <bits/stdc++.h>
    using namespace std;
    /*
    segtree[1].num - arr[i].p
    本题存在坑点,不同种类的树有相同的高度
    将不同种类的树 放到相同高度的vector里面
    枚举高度
    存在一个前缀和
    */
    typedef long long LL;
    int n;
    const int MAXN = 1e5 + 5;
    struct Tree{
        LL h, c, p;
        friend bool operator< (const Tree &a, const Tree &b){
            return a.h < b.h;
        }
    }arr[MAXN];
    LL sum[MAXN];
    vector<LL>vec, h_arr;
    vector<int>vec_tree[MAXN];
    struct Segtree{
        struct NODE{
            int l, r;
            LL sum, num;
        }tree[MAXN << 2];
        void Init(){
            for(int i = 0; i <= 4 * n; i ++){
                tree[i].l = tree[i].r = tree[i].sum = tree[i].num = 0;
            }
        }
        inline void push_up(int root){
            tree[root].sum = tree[root << 1].sum + tree[root << 1 | 1].sum;
            tree[root].num = tree[root << 1].num + tree[root << 1 | 1].num;
            return ;
        }
        void build(int root, int l, int r){
            tree[root].l = l, tree[root].r = r;
            if(l == r){
                tree[root].sum = tree[root].num = 0;
                return ;
            }
            int mid = (l + r) >> 1;
            build(root << 1, l, mid);
            build(root << 1 | 1, mid + 1, r);
            return ;
        }
        void update(int root, int cnt, LL val){
            if(tree[root].l == cnt && tree[root].r == cnt){
                tree[root].sum += val * vec[cnt - 1];
                tree[root].num += val;
                return ;
            }
            int mid = (tree[root].l + tree[root].r) >> 1;
            if(cnt <= mid){
                update(root << 1, cnt, val);
            }
            else{
                update(root << 1 | 1, cnt, val);
            }
            push_up(root);
        }
        LL query(int root, LL cnt){
            if(tree[root].num == cnt){
                return tree[root].sum;
            }
            if(tree[root].l == tree[root].r){
                return vec[tree[root].l - 1] * cnt;
            }
            if(cnt > tree[root << 1].num){
                return query(root << 1, tree[root << 1].num) + query(root << 1 | 1, cnt - tree[root << 1].num);
            }
            else{
                return query(root << 1, cnt);
            }
        }
    }seg;
    int Get(LL x){
        return lower_bound(vec.begin(), vec.end(), x) - vec.begin() + 1;
    }
    int Geth(LL x){
        return lower_bound(h_arr.begin(), h_arr.end(), x) - h_arr.begin() + 1;
    }
    int main(){
        while(~scanf("%d", &n)){
            memset(sum, 0, (n + 3) * sizeof(sum[0]));
            vec.clear(), h_arr.clear();
            for(int i = 0; i <= n; i ++){
                vec_tree[i].clear();
            }
            seg.Init();
            for(int i = 0; i < n; i ++){
                scanf("%lld%lld%lld", &arr[i].h, &arr[i].c, &arr[i].p);
                vec.push_back(arr[i].c), h_arr.push_back(arr[i].h);
            }
            sort(arr, arr + n);
            sort(vec.begin(), vec.end());
            vec.erase(unique(vec.begin(), vec.end()), vec.end());
            sort(h_arr.begin(), h_arr.end());
            h_arr.erase(unique(h_arr.begin(), h_arr.end()), h_arr.end());
            sum[0] = arr[0].p * arr[0].c;
            for(int i = 1; i < n; i ++){
                sum[i] = sum[i - 1] + arr[i].p * arr[i].c;
            }
            seg.build(1, 1, n);
            for(int i = 0; i < n; i ++){
                vec_tree[Geth(arr[i].h)].push_back(i);
            }
            LL ans = __LONG_LONG_MAX__;
            for(int i = 1; i <= h_arr.size(); i ++){
                LL sums = 0;
                for(int j = 0; j < vec_tree[i].size(); j ++){
                    sums += arr[vec_tree[i][j]].p;
                }
                if(sums > seg.tree[1].num){
                    ans = min(ans, sum[n - 1] - sum[vec_tree[i][vec_tree[i].size() - 1]]);
                }
                else{
                    ans = min(ans, sum[n - 1] - sum[vec_tree[i][vec_tree[i].size() - 1]] + seg.query(1, seg.tree[1].num - sums + 1));
                }
                for(int j = 0; j < vec_tree[i].size(); j ++){
                    seg.update(1, Get(arr[vec_tree[i][j]].c), arr[vec_tree[i][j]].p);
                }
            }
            printf("%lld
    ", ans);
        } 
        return 0;
    }
    
  • 相关阅读:
    探索式测试实践之路
    管理是什么?真正的管理者是,“管”+“理”!
    JavaScript中的函数式编程
    node js的终端中 console.log 嵌套对象会被折叠的问题
    apt-get install的默认安装路径
    nodejs 事件循环 试题思考
    仅20行的JavaScript模板引擎
    js 驼峰命名转烤串
    git reset 进阶
    linux 拷贝文本到剪切板
  • 原文地址:https://www.cnblogs.com/qq136155330/p/11366622.html
Copyright © 2011-2022 走看看