牛客多校第七场 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); } }