牛客多校第七场 C Governing sand 线段树

题意:

有一个树林,树林中不同种类的树有不同的数量,高度,砍伐它们的价格。现在要求砍掉一些树,使得高度最高的树占剩下的树的总数的一半以上,求最小花费。

题解:

用线段树维护不同种类树的信息,叶子节点从左到右存储单棵砍伐花费最小的树,从高度由高到低枚举树的种类,每次记这种树为留下的最高的树,每次将此种树从线段树上删除,然后求线段树上,使得矮树与高树比例满足要求的前缀和,还要记录比它高的树砍掉的总花费。

注意多种树同一高度要特殊处理。

#include<bits/stdc++.h>
#define MAXN 100005
#define LL long long
using namespace std;
struct Node{
    int l,r;
    int oneval;
    LL sumnum;
    LL sumval;
}node[MAXN<<2];
struct Tree{
    int oneval;
    int num;
    int height;
    int valrank;
}tree[MAXN];
inline bool cmp1(const Tree &a,const Tree &b){
    return a.oneval<b.oneval;
}
inline bool cmp2(const Tree &a,const Tree &b){
    return a.height>b.height;
}
void build(int l,int r,int x){
    node[x].l=l;
    node[x].r=r;
    if(l==r){
        node[x].sumnum=tree[l].num;
        node[x].oneval=tree[l].oneval;
        node[x].sumval=1LL*tree[l].num*tree[l].oneval;
        return ;
    }else{
        int mid=(l+r)/2;
        build(l,mid,x*2);
        build(mid+1,r,x*2+1);
    }
    node[x].sumnum=node[2*x].sumnum+node[2*x+1].sumnum;
    node[x].sumval=node[2*x].sumval+node[2*x+1].sumval;
    return ;
}
//LL query(int l,int r,int x){
//    if(l<=node[x].l && node[x].r<=r)return node[x].exis;
//    if(node[x].r<l || r<node[x].l)return 0;
//    LL ans=0;
//    if(l<=node[x*2].r)ans+=query(l,r,2*x);
//    if(node[x*2+1].l<=r)ans+=query(l,r,2*x+1);
//    return ans;
//}
void erase(int id,int x){
    if(node[x].l==node[x].r){
        node[x].sumnum=0;
        node[x].sumval=0;
        node[x].oneval=0;
        return ;
    }
    if(id<=node[x*2].r){
        erase(id,x*2);
    }else{
        erase(id,x*2+1);
    }
    node[x].sumval=node[x*2].sumval+node[x*2+1].sumval;
    node[x].sumnum=node[x*2].sumnum+node[x*2+1].sumnum;
    return ;
}
LL bsearch(LL last,int x){
    if(last<=0)return 0;
    if(node[x].l==node[x].r)return last*node[x].oneval;
    if(node[x].sumnum==last)return node[x].sumval;
    if(node[x].sumnum>last){
        if(last<=node[x*2].sumnum)return bsearch(last,x*2);
        else return node[x*2].sumval+bsearch(last-node[x*2].sumnum,x*2+1);
    }
}
int main(){
    int n;
    while(~scanf("%d",&n)){
        LL nowtrees=0;
        LL nowcost=0;
        LL minn=0x3f3f3f3f3f3f3f3f;
        for(int i=1;i<=n;i++){
            scanf("%d %d %d",&tree[i].height,&tree[i].oneval,&tree[i].num);
            nowtrees+=tree[i].num;
        }
        sort(tree+1,tree+1+n,cmp1);
        for(int i=1;i<=n;i++){
            tree[i].valrank=i;
        }
        build(1,n,1);
        sort(tree+1,tree+1+n,cmp2);
        for(int i=1;i<=n;i++){
            LL nextcost=0;
            LL talltrees=0;
            while(i<n && tree[i+1].height==tree[i].height){
                nowtrees-=tree[i].num;
                talltrees+=tree[i].num;
                erase(tree[i].valrank,1);
                nextcost+=1LL*tree[i].num*tree[i].oneval;
                ++i;
            }
            nowtrees-=tree[i].num;
            talltrees+=tree[i].num;
            erase(tree[i].valrank,1);
            nextcost+=1LL*tree[i].num*tree[i].oneval;
             
            minn=min(minn,nowcost+bsearch(nowtrees-talltrees+1,1));
//          printf("time%d:%lld\n",i,nowcost+bsearch(nowtrees-talltrees+1,1));
             
            nowcost+=nextcost;
        }
        printf("%lld\n",minn);
    }
}

 

posted @ 2019-08-09 21:34  Isakovsky  阅读(175)  评论(0编辑  收藏  举报