题意:

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

题解:

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

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

  1. #include<bits/stdc++.h>
  2. #define MAXN 100005
  3. #define LL long long
  4. using namespace std;
  5. struct Node{
  6. int l,r;
  7. int oneval;
  8. LL sumnum;
  9. LL sumval;
  10. }node[MAXN<<];
  11. struct Tree{
  12. int oneval;
  13. int num;
  14. int height;
  15. int valrank;
  16. }tree[MAXN];
  17. inline bool cmp1(const Tree &a,const Tree &b){
  18. return a.oneval<b.oneval;
  19. }
  20. inline bool cmp2(const Tree &a,const Tree &b){
  21. return a.height>b.height;
  22. }
  23. void build(int l,int r,int x){
  24. node[x].l=l;
  25. node[x].r=r;
  26. if(l==r){
  27. node[x].sumnum=tree[l].num;
  28. node[x].oneval=tree[l].oneval;
  29. node[x].sumval=1LL*tree[l].num*tree[l].oneval;
  30. return ;
  31. }else{
  32. int mid=(l+r)/;
  33. build(l,mid,x*);
  34. build(mid+,r,x*+);
  35. }
  36. node[x].sumnum=node[*x].sumnum+node[*x+].sumnum;
  37. node[x].sumval=node[*x].sumval+node[*x+].sumval;
  38. return ;
  39. }
  40. //LL query(int l,int r,int x){
  41. // if(l<=node[x].l && node[x].r<=r)return node[x].exis;
  42. // if(node[x].r<l || r<node[x].l)return 0;
  43. // LL ans=0;
  44. // if(l<=node[x*2].r)ans+=query(l,r,2*x);
  45. // if(node[x*2+1].l<=r)ans+=query(l,r,2*x+1);
  46. // return ans;
  47. //}
  48. void erase(int id,int x){
  49. if(node[x].l==node[x].r){
  50. node[x].sumnum=;
  51. node[x].sumval=;
  52. node[x].oneval=;
  53. return ;
  54. }
  55. if(id<=node[x*].r){
  56. erase(id,x*);
  57. }else{
  58. erase(id,x*+);
  59. }
  60. node[x].sumval=node[x*].sumval+node[x*+].sumval;
  61. node[x].sumnum=node[x*].sumnum+node[x*+].sumnum;
  62. return ;
  63. }
  64. LL bsearch(LL last,int x){
  65. if(last<=)return ;
  66. if(node[x].l==node[x].r)return last*node[x].oneval;
  67. if(node[x].sumnum==last)return node[x].sumval;
  68. if(node[x].sumnum>last){
  69. if(last<=node[x*].sumnum)return bsearch(last,x*);
  70. else return node[x*].sumval+bsearch(last-node[x*].sumnum,x*+);
  71. }
  72. }
  73. int main(){
  74. int n;
  75. while(~scanf("%d",&n)){
  76. LL nowtrees=;
  77. LL nowcost=;
  78. LL minn=0x3f3f3f3f3f3f3f3f;
  79. for(int i=;i<=n;i++){
  80. scanf("%d %d %d",&tree[i].height,&tree[i].oneval,&tree[i].num);
  81. nowtrees+=tree[i].num;
  82. }
  83. sort(tree+,tree++n,cmp1);
  84. for(int i=;i<=n;i++){
  85. tree[i].valrank=i;
  86. }
  87. build(,n,);
  88. sort(tree+,tree++n,cmp2);
  89. for(int i=;i<=n;i++){
  90. LL nextcost=;
  91. LL talltrees=;
  92. while(i<n && tree[i+].height==tree[i].height){
  93. nowtrees-=tree[i].num;
  94. talltrees+=tree[i].num;
  95. erase(tree[i].valrank,);
  96. nextcost+=1LL*tree[i].num*tree[i].oneval;
  97. ++i;
  98. }
  99. nowtrees-=tree[i].num;
  100. talltrees+=tree[i].num;
  101. erase(tree[i].valrank,);
  102. nextcost+=1LL*tree[i].num*tree[i].oneval;
  103.  
  104. minn=min(minn,nowcost+bsearch(nowtrees-talltrees+,));
  105. // printf("time%d:%lld\n",i,nowcost+bsearch(nowtrees-talltrees+1,1));
  106.  
  107. nowcost+=nextcost;
  108. }
  109. printf("%lld\n",minn);
  110. }
  111. }

牛客多校第七场 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. 【leetcode】962. Maximum Width Ramp

    题目如下: Given an array A of integers, a ramp is a tuple (i, j) for which i < j and A[i] <= A[j]. ...

  2. python基础特性之函数property

    函数property 1.为了保护属性,不让它随意的被更改(a.width=xxx)(起码,要符合某些条件),所以我们引入了set和get方法,虽然这个需要自定义(如下图的set_size,get_s ...

  3. MyEclipse6.0中使用aptana插件,添加jquery提示功能

    MyEclipse6.0中使用aptana插件,添加jquery提示功能 第一:查看当前MyEclipse集成的eclipse的版本,, 查看路径    D:/MyEclipse 6.0/eclips ...

  4. 基础(三):yum(RedHat系列)和apt-get(Debian系列 )用法及区别

    文章转载来自:http://blog.csdn.net/chengly0129/article/details/70169760 一般来说著名的linux系统基本上分两大类:1.RedHat系列:Re ...

  5. CSS:CSS 背景

    ylbtech-CSS:CSS 背景 1.返回顶部 1. CSS 背景 CSS 背景属性用于定义HTML元素的背景. CSS 属性定义背景效果: background-color background ...

  6. jsp+servlet中文乱码问题

    jsp+servlet中文乱码问题 servlet想要获得前台传来的值 String strName=new String(request.getParameter("name") ...

  7. Spring 学习笔记 IoC 基础

    Spring IoC Ioc 是什么 IoC -- Inversion of Control(控制反转)什么是控制?什么是反转? 控制反转了什么? 在很早之前写项目不用 Spring 的时候,都是在 ...

  8. 前端(十八)—— jQuery高级操作:选择器、文本属性与类、事件、文档操作、动画、结构关系

    JQ选择器.文本属性与类.事件.文档操作.动画.结构关系 可参考jQuery的API文档 一.选择器 1.css语法匹配 标签 | 类 | id | 交集 群组 | 后代 | 兄弟 伪类 | 属性 $ ...

  9. Java中的注解是如何工作的?

    自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述 ...

  10. python 中 random模块的用法

    import random print( random.randint(1,10) ) # 产生 1 到 10 的一个整数型随机数 print( random.random() ) # 产生 0 到 ...