题意:

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

题解:

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

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

#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<<];
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)/;
build(l,mid,x*);
build(mid+,r,x*+);
}
node[x].sumnum=node[*x].sumnum+node[*x+].sumnum;
node[x].sumval=node[*x].sumval+node[*x+].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=;
node[x].sumval=;
node[x].oneval=;
return ;
}
if(id<=node[x*].r){
erase(id,x*);
}else{
erase(id,x*+);
}
node[x].sumval=node[x*].sumval+node[x*+].sumval;
node[x].sumnum=node[x*].sumnum+node[x*+].sumnum;
return ;
}
LL bsearch(LL last,int x){
if(last<=)return ;
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*].sumnum)return bsearch(last,x*);
else return node[x*].sumval+bsearch(last-node[x*].sumnum,x*+);
}
}
int main(){
int n;
while(~scanf("%d",&n)){
LL nowtrees=;
LL nowcost=;
LL minn=0x3f3f3f3f3f3f3f3f;
for(int i=;i<=n;i++){
scanf("%d %d %d",&tree[i].height,&tree[i].oneval,&tree[i].num);
nowtrees+=tree[i].num;
}
sort(tree+,tree++n,cmp1);
for(int i=;i<=n;i++){
tree[i].valrank=i;
}
build(,n,);
sort(tree+,tree++n,cmp2);
for(int i=;i<=n;i++){
LL nextcost=;
LL talltrees=;
while(i<n && tree[i+].height==tree[i].height){
nowtrees-=tree[i].num;
talltrees+=tree[i].num;
erase(tree[i].valrank,);
nextcost+=1LL*tree[i].num*tree[i].oneval;
++i;
}
nowtrees-=tree[i].num;
talltrees+=tree[i].num;
erase(tree[i].valrank,);
nextcost+=1LL*tree[i].num*tree[i].oneval; minn=min(minn,nowcost+bsearch(nowtrees-talltrees+,));
// printf("time%d:%lld\n",i,nowcost+bsearch(nowtrees-talltrees+1,1)); nowcost+=nextcost;
}
printf("%lld\n",minn);
}
}

牛客多校第七场 C Governing sand 线段树的更多相关文章

  1. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  2. 2019年牛客多校第四场 B题xor(线段树+线性基交)

    题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...

  3. 2019牛客多校第四场C-sequence(单调栈+线段树)

    sequence 题目传送门 解题思路 用单调栈求出每个a[i]作为最小值的最大范围.对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要 ...

  4. 牛客多校第十场 F Popping Balloons 线段树维护稀疏矩阵

    题意: 给定一个稀疏矩阵,里面有若干个气球,让你横着开三枪,竖着开三枪,问最多能打爆多少气球,要求相同方向,相邻两枪必须间隔r. 题解: 横向记录每列有多少个气球,分别在哪行上. 然后把这个数据改造成 ...

  5. 2019牛客训练赛第七场 C Governing sand 权值线段树+贪心

    Governing sand 题意 森林里有m种树木,每种树木有一定高度,并且砍掉他要消耗一定的代价,问消耗最少多少代价可以使得森林中最高的树木大于所有树的一半 分析 复杂度分析:n 1e5种树木,并 ...

  6. 牛客多校第七场 C Bit Compression 思维

    链接:https://www.nowcoder.com/acm/contest/145/C来源:牛客网 A binary string s of length N = 2n is given. You ...

  7. Find the median(2019年牛客多校第七场E题+左闭右开线段树)

    题目链接 传送门 题意 每次往集合里面添加一段连续区间的数,然后询问当前集合内的中位数. 思路 思路很好想,但是卡内存. 当时写的动态开点线段树没卡过去,赛后机房大佬用动态开点过了,\(tql\). ...

  8. 2019牛客多校第七场E Find the median 权值线段树+离散化

    Find the median 题目链接: https://ac.nowcoder.com/acm/contest/887/E 题目描述 Let median of some array be the ...

  9. 两两内积为0(牛客多校第七场)-- CDMA

    题意: 构造一个n*n的矩阵,元素只能是-1或1,任意两行内积为0(两两相乘加起来和为0). 思路: #define IOS ios_base::sync_with_stdio(0); cin.tie ...

随机推荐

  1. mongodb客户端操作常用命令(续)

    之前有写过一篇mongodb客户端的操作常用命令 ,今天接着来记录分享一些关于mongodb账户权限设置的命令操作 上期mongodb客户端的操作常用命令地址:https://www.cnblogs. ...

  2. go结构体上的函数

    go结构体上的函数 我们可以将一个方法和一个结构体关联: type Saiyan struct { Name string Power int } func (s *Saiyan) Super() { ...

  3. Dataphin支持哪些数据源

    业务数据存储是业务系统最基本的构成,构建数据中台,就是要将这些数据集中起来放到一个有更强算力的地方集中处理,所以对于数据集成的能力是构建数据中台最基本要求: 从存储的发展历程来看,由于不同的业务场景需 ...

  4. Shiro学习(23)多项目集中权限管理

    在做一些企业内部项目时或一些互联网后台时:可能会涉及到集中权限管理,统一进行多项目的权限管理:另外也需要统一的会话管理,即实现单点身份认证和授权控制. 学习本章之前,请务必先学习<第十章 会话管 ...

  5. 【LeetCode 25】K 个一组翻转链表

    题目链接 [题解] 模拟就好. 就k个k个节点地翻转. 每个节点都把next域指向它前面那个节点 修改完之后把这个节点前面的那个节点的next域改成这一段的最后一个节点. 然后把这一段最左边的那个节点 ...

  6. java EE学习流程(第二版更新)

    这周有点堕落了,这两天啥都没写,就顾上刷<庆余年>了

  7. (转)短信vs.推送通知vs.电子邮件:app什么时候该用哪种方式来通知用户?

    转:http://www.360doc.com/content/15/0811/00/19476362_490860835.shtml 现在,很多公司都关心的一个问题是:要提高用户互动,到底采取哪一种 ...

  8. (转)Vmware vSphere 5.0系列教程 vSphere网络原理及vSwitch简介 及一个host两个网卡说明

    转:http://andygao.blog.51cto.com/323260/817518/ 在一个物理网络拓扑中,通常都是路由器-交换机-PC机的连接,不同的服务器和PC机,通过交换机的连接而相互连 ...

  9. 关于类中的参数类型和return返回值

    基础有些忘了,现在重新巩固一下 先定义一个Person类 class Person(): def __init__(self,name,age,height): self.name=name, sel ...

  10. 记一次批量修改SQLServer表数据

    前提: 1.数据有上百万条,分成10几张excel表,从数据库中导出,由业务部门修改: 2.数据没什么规律: 3.和数据库DB商量后决定先把从excel导进数据库中,再通过关联查询修改数据 将 Exc ...