题面描述:有一片树林,要求砍掉一些树,使得最高的树的数量占总数量的一半以上,每种树有高度,数量,以及砍掉需要的花费。求最小花费。
思路:将每种树按高度排序后,从低到高枚举最高的树的高度,然后判断最小花费。cost最多200,每次查询最多两百次,时间足够。
比当前最高的树需要全部砍掉,可以预处理答案,枚举时实时修改。要注意的是不同树的高度可能不同,计算数量时要考虑,另外修改已有树的数量要在当前高度的树处理完毕后,否则会对计算结果造成干扰。
#include<bits/stdc++.h> using namespace std; #define ll long long #define mem(a) memset(a,0,sizeof a) #define pii pair<int,int> const int N=1e5+5; const int INF=1e9+5; ll read(ll &a){scanf("%lld",&a);return a;} int read(int &a){scanf("%d",&a);return a;} int read(){int a;scanf("%d",&a);return a;} int read(int &a,int &b){scanf("%d %d",&a,&b);return a;} int n; struct node{ ll h,c,p; }a[N]; ll leftans; //ll leftcnt; ll cnt[210]; void scan(){ leftans=0; //leftcnt=0; for(int i=0;i<n;i++){ scanf("%lld%lld%lld",&a[i].h,&a[i].c,&a[i].p); leftans+=a[i].c*a[i].p; //leftcnt+=a[i].p; } } bool cmp(node x,node y){ return x.h<y.h; } void solve(){ sort(a,a+n,cmp); //a[n].h=0; mem(cnt); ll high=0; ll highcnt=0; ll needcut=0; ll ans=1e18+7; ll temp; ll all=0; queue<node>q; for(int i=0;i<n;i++){ //leftcnt-=a[i].p; leftans-=a[i].p*a[i].c; all+=a[i].p; temp=leftans; if(a[i].h>high){ highcnt=a[i].p; while(!q.empty()){ cnt[q.front().c]+=q.front().p; q.pop(); } } else highcnt+=a[i].p; high=a[i].h; needcut=all-(highcnt+highcnt-1); if(needcut>0){ for(int j=1;j<=200&&needcut>0;j++){ if(needcut>=cnt[j]){ needcut-=cnt[j]; temp+=cnt[j]*j; } else{ temp+=needcut*j; needcut=0; break; } } } ans=min(ans,temp); q.push(a[i]); //cnt[a[i].c]+=a[i].p; } printf("%lld\n",ans); } int main() { while(~scanf("%d",&n)){ scan(); solve(); } return 0; }