示例:
输入:
2
5 1 1
1 10 1
2
5 1 2
3 2 3
输出:
1
2

题意:n种树,第i种树有P[i]颗,砍掉每颗树的代价是C[i], 高度是H[i]。需要用最小的花费砍掉一些树,让最高的树超过一半。

题解:按高度分类,从小到大枚举最大高度,比当前枚举的高度 h 要高的,一定删,比它小的,如果删前 ? 小的。

贪心代码:

 #include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxx=1e5+;
struct node{
ll h,v,p;
bool operator<(const node&a)const{
return h<a.h;
}
}tree[maxx];
ll B[],arr[maxx],pre[maxx];//B储存已经遍历过的树在该价值的数量,arr储存第i高及比第i高的树都被砍掉的花费,pre储存第i高树矮的树的数量
int main()
{
ll n;
while(~scanf("%lld",&n)){
memset(B,,sizeof(B));
for(int i=;i<=n;i++)scanf("%lld%lld%lld",&tree[i].h,&tree[i].v,&tree[i].p);
sort(tree+,tree++n);//从低到高排序高度
arr[n+]=;
for(int i=n;i>=;i--)arr[i]=arr[i+]+tree[i].v*tree[i].p;
pre[]=;
for(int i=;i<=n;i++)pre[i]=pre[i-]+tree[i].p;
ll ans=1e18;
for(int i=,j=;i<=n;i=j){//从小到大枚举最大高度
while(j<=n&&tree[j].h==tree[i].h)j++;
ll sums=;
for(int k=i;k<j;k++)sums+=tree[k].p;
ll cost=arr[j];
if(sums<=pre[i-]){//如果第i高的树的数量小于比它矮的树的数量,即将价值数组进行从小到大处理
ll need=pre[i-]-sums+;
for(int t=;t<=;t++){
if(B[t]<=need){
cost+=B[t]*t;
need-=B[t];
}else{
cost+=need*t;
break;
}
}
}
ans=min(ans,cost);
for(int k=i;k<j;k++)B[tree[k].v]+=tree[k].p;
}
printf("%lld\n",ans);
}
return ;
}

主席树代码:

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int maxx=2e5+;
int tot;
struct Node{
LL h,v,p;
bool operator <(const Node &a)const
{
return a.h>h;
}
}tree[maxx];
struct node{
LL l,r,sum,num;
}p[maxx*];
LL v[maxx],root[maxx];
LL update(LL rot,LL l,LL r,LL pos,LL num)//建立主席树
{
LL book=++tot;
p[book]=p[rot];//传递上一颗主席树的性质进行修改
p[book].num+=(LL)num;
p[book].sum+=(LL)pos*(LL)num;
if(l==r) return book;
LL mid=l+r>>;
if(pos<=mid) p[book].l=update(p[rot].l,l,mid,pos,num);
else p[book].r=update(p[rot].r,mid+,r,pos,num);
return book;
}
LL query(LL rot,LL l,LL r,LL num)//查询
{
if(l==r) return (LL)l*(LL)num;
LL ans=p[p[rot].l].num;
LL mid=l+r>>;
if(num<=ans) return query(p[rot].l,l,mid,num);
else
{
return p[p[rot].l].sum+query(p[rot].r,mid+,r,num-ans);
}
}
int main()
{
int n;
while(~scanf("%lld",&n)){
tot=;
memset(v,,sizeof(v));
for(int i=;i<=n;i++){
scanf("%lld%lld%lld",&tree[i].h,&tree[i].v,&tree[i].p);
}
sort(tree+,tree+n+);
for(int i=;i<=n;i++)
v[i]=v[i-]+tree[i].p;
for(int i=;i<=n;i++){
root[i]=update(root[i-],,,tree[i].v,tree[i].p);//主席树记录每种树的根节点
}
LL Minn=1e18,moneys=;
for(int i=n;i>=;i--){
LL treenum=,sums=;
while(tree[i].h==tree[i-].h){
treenum+=tree[i].v*tree[i].p;
sums+=tree[i].p;
i--;
}
treenum+=tree[i].v*tree[i].p;
sums+=tree[i].p;
LL Smoney=;
if(v[i-]>=sums)Smoney=moneys+query(root[i-],,,v[i-]-sums+);//如果第i高的树的数量小于比它矮的树的数量,查询前i-1种树中的需要砍的树的花费
else Smoney=moneys;
Minn=min(Minn,Smoney);
moneys+=treenum;//记录比第i种树高的树的砍掉的花费
}
printf("%lld\n",Minn);
}
return ;
}

Governing sand(主席树/贪心)(2019牛客暑期多校训练营(第七场))的更多相关文章

  1. 2019牛客暑期多校训练营(第九场)H Cutting Bamboos(主席树+二分)

    题意:n个竹子,有高度,q次询问,询问之间是独立的,每次查询输入l,r,x,y代表砍区间[l,r]]内的竹子砍y次,最后一次要砍成0,每次砍掉的总长度相同,问第x次砍的高度是多少. 既然每次要求砍掉的 ...

  2. 2019牛客暑期多校训练营(第九场)A:Power of Fibonacci(斐波拉契幂次和)

    题意:求Σfi^m%p. zoj上p是1e9+7,牛客是1e9:  对于这两个,分别有不同的做法. 前者利用公式,公式里面有sqrt(5),我们只需要二次剩余求即可.     后者mod=1e9,5才 ...

  3. 2019牛客暑期多校训练营(第一场)A题【单调栈】(补题)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 题目描述 Two arrays u and v each with m distinct elem ...

  4. 2019牛客暑期多校训练营(第一场) B Integration (数学)

    链接:https://ac.nowcoder.com/acm/contest/881/B 来源:牛客网 Integration 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 5242 ...

  5. 2019牛客暑期多校训练营(第一场) A Equivalent Prefixes ( st 表 + 二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A 来源:牛客网 Equivalent Prefixes 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/ ...

  6. 2019牛客暑期多校训练营(第二场)F.Partition problem

    链接:https://ac.nowcoder.com/acm/contest/882/F来源:牛客网 Given 2N people, you need to assign each of them ...

  7. 2019牛客暑期多校训练营(第一场)A Equivalent Prefixes(单调栈/二分+分治)

    链接:https://ac.nowcoder.com/acm/contest/881/A来源:牛客网 Two arrays u and v each with m distinct elements ...

  8. [状态压缩,折半搜索] 2019牛客暑期多校训练营(第九场)Knapsack Cryptosystem

    链接:https://ac.nowcoder.com/acm/contest/889/D来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 262144K,其他语言52428 ...

  9. DP+线段树维护矩阵(2019牛客暑期多校训练营(第二场))--MAZE

    题意:https://ac.nowcoder.com/acm/contest/882/E 给你01矩阵,有两种操作:1是把一个位置0变1.1变0,2是问你从第一行i开始,到最后一行j有几种走法.你只能 ...

  10. Points Division(线段树+DP)2019牛客暑期多校训练营(第一场)

    题意:https://ac.nowcoder.com/acm/contest/881/I 给你n个平面上的点,每个点有a.b两个权值,现在让你划分成两个区域(要求所有A集合里的点不能在任何B集合里的点 ...

随机推荐

  1. maven install

    1. install maven under ubuntu apt install maven 2 speed up package download vim ~/.m2/settings.xml & ...

  2. Selenium ChromeDriver与Chrome版本映射表(更新到v77)

    ChromeDriver版本 支持的Chrome版本 v77.0.3865.40 v77 v76.0.3809.126 v76 v75.0.3770.140 v75 v74 v74 v73 v73 v ...

  3. Linux 系统管理——磁盘管理及文件系统实例

    1.为主机新增两块30GB的SCSI硬盘 2.划分3个主分区,各5GB,剩余空间作为扩展分区 3.在扩展分区中建立2个逻辑分区,容量分别为2GB.10GB 4.将第一个逻辑分区的类型改为swap 5. ...

  4. Web前端开发工具和环境清单

    初级 浏览器 Google Chrome 75.0.3770.100www.google.cn/intl/zh-CN/chrome初级 移动端模拟器 Genymotion 6.0.6www.genym ...

  5. 使用python3完成人脸识别

    原文地址:https://www.jb51.net/article/160197.htm 第一种: # -*- coding:utf-8 -*- import cv2 as cv import num ...

  6. Monkey框架(基础知识篇) - monkey启动与参数介绍

    一.monkey启动 直接PC启动:> adb shell monkey [options] <count> shell 端启动:> adb shell >monkey ...

  7. C# 最简单的使程序单进程运行的方法

    1.代码1 static void Main() { Process current = Process.GetCurrentProcess(); Process[] processes = Proc ...

  8. Java文件上传下载原理

    文件上传下载原理 在TCP/IP中,最早出现的文件上传机制是FTP.它是将文件由客户端发送到服务器的标准机制. 但是在jsp编程中不能使用FTP方法来上传文件,这是由jsp运行机制所决定的 文件上传原 ...

  9. Python3基础 yield send 获得生成器后,需要先启动一次

             Python : 3.7.3          OS : Ubuntu 18.04.2 LTS         IDE : pycharm-community-2019.1.3    ...

  10. GSON工具类

    import java.util.Map; import com.google.gson.reflect.TypeToken; import com.google.gson.FieldNamingPo ...