题目链接:https://ac.nowcoder.com/acm/contest/887/C?&headNav=acm

题意:

给你 n 种树,有 高度,花费和数量 ,现在问你最少需要花多少钱使得最高的树的数量占总数的一半以上。

思路:

其实就是先把高度离散化一下(不离散化也没事),再按树的高度从低到高排一下序,枚举最高的树。

比如当前枚举的是 H,那花费就是(>H)的树的所有花费+(<H)的最多剩下num-1棵树,用权值线段树记录花费和花费的个数,每次查询前k小个就可以了。

 #define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#include <cstdio>//sprintf islower isupper
#include <cstdlib>//malloc exit strcat itoa system("cls")
#include <iostream>//pair
#include <fstream>
#include <bitset>
//#include <map>
//#include<unordered_map> https://ac.nowcoder.com/acm/contest/887/C?&headNav=acm
#include <vector>
#include <stack>
#include <set>
#include <string.h>//strstr substr
#include <string>
#include <time.h>//srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9;
#include <cmath>
#include <deque>
#include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
#include <vector>//emplace_back
//#include <math.h>
//#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor
#include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare)
using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
#define fo(a,b,c) for(register int a=b;a<=c;++a)
#define fr(a,b,c) for(register int a=b;a>=c;--a)
#define mem(a,b) memset(a,b,sizeof(a))
#define pr printf
#define sc scanf
#define ls rt<<1
#define rs rt<<1|1
void swapp(int &a,int &b);
double fabss(double a);
int maxx(int a,int b);
int minn(int a,int b);
int Del_bit_1(int n);
int lowbit(int n);
int abss(int a);
const long long INF=(1LL<<);
const double E=2.718281828;
const double PI=acos(-1.0);
const int inf=(<<);
const double ESP=1e-;
const int mod=(int)1e9+;
const int N=(int)1e5+; int n;
struct node_
{
int h,num,cost;
friend bool operator<(node_ a,node_ b)
{
return a.h>b.h;
}
}arr[N];
int b[N];
int LS(int n)
{
int m=;
for(int i=; i<=n; ++i)
b[++m]=arr[i].h;
sort(b+,b++m);
m=unique(b+,b++m)-b-;
for(int i=; i<=n; ++i)
arr[i].h=lower_bound(b+,b++m,arr[i].h)-b;
return m;
}
//================================================离散化;
struct node
{
long long cnt;
long long sum;
}tr[N<<];
void Build(int l,int r,int rt)
{
tr[rt].sum=tr[rt].cnt=;
if(l==r)return;
int mid=(l+r)>>;
Build(l,mid,rt<<);
Build(mid+,r,rt<<|);
}
void update_dot(int cost,int cnt,int l,int r,int rt)
{
tr[rt].sum+=cost*cnt;
tr[rt].cnt+=cnt;
if(l==r)return; int mid=(l+r)>>;
if(cost<=mid)
update_dot(cost,cnt,l,mid,rt<<);
else
update_dot(cost,cnt,mid+,r,rt<<|);
}
long long Query(long long sum,int l,int r,int rt)
{
if(sum==)return ;
if(l==r)
{
return sum*l;
}
int mid=(l+r)>>;
long long ans=; if(sum<=tr[ls].cnt)
ans+=Query(sum,l,mid,ls);
else
ans+=Query(sum-tr[ls].cnt,mid+,r,rs)+tr[ls].sum;
return ans;
}
void check(int pos,int l,int r,int rt)
{
if(l==r)
{
pr("%lld %lld\n",tr[rt].cnt,tr[rt].sum);
return ;
}
int mid=(l+r)>>; if(pos<=mid)
check(pos,l,mid,rt<<);
else
check(pos,mid+,r,rt<<|);
}
void C(int tot)
{
fo(i,,n)
check(i,,tot,);
pr("----------------------------------\n");
}
long long dp[N];
vector<vector<int> >v(N); int main()
{
while(~sc("%d",&n))
{
fo(i,,n)sc("%d%d%d",&arr[i].h,&arr[i].cost,&arr[i].num);
arr[n+].num=arr[n+].cost=arr[n+].h=;
LS(n);
sort(arr+,arr++n);
fo(i,,n)
dp[i]=dp[i-]+arr[i].cost*arr[i].num,v[i].clear();
long long ans=INF;
int vcnt=;
long long cnt=;
long long CNT=;
int ncnt=;
for(int i=n;i>=;--i)
{
if(arr[i].h!=arr[i+].h)
v[++vcnt].push_back(i);
else
v[vcnt].push_back(i);
}
Build(,,);
int sz=v[].size();//vector用来存相同高度的树团体
fo(i,,sz-)
update_dot(arr[v[][i]].cost,arr[v[][i]].num,,,),CNT+=arr[v[][i]].num;
ans=min(ans,dp[n-sz]);
ncnt=sz;
fo(i,,vcnt)
{
int sz_=v[i].size();
fo(j,,sz_-)
cnt+=arr[v[i][j]].num;
ncnt+=sz_;
long long k=max(0LL,CNT-(cnt-));
ans=min(ans,Query(k,,,)+dp[n-ncnt]);
fo(j,,sz_-)
update_dot(arr[v[i][j]].cost,arr[v[i][j]].num,,,);
CNT+=cnt;
cnt=;
}
pr("%lld\n",ans);
}
return ;
} /**************************************************************************************/ int maxx(int a,int b)
{
return a>b?a:b;
} void swapp(int &a,int &b)
{
a^=b^=a^=b;
} int lowbit(int n)
{
return n&(-n);
} int Del_bit_1(int n)
{
return n&(n-);
} int abss(int a)
{
return a>?a:-a;
} double fabss(double a)
{
return a>?a:-a;
} int minn(int a,int b)
{
return a<b?a:b;
}

区间前k小的和(权值线段树+离散化)--2019牛客多校第7场C--砍树的更多相关文章

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

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

  2. 2019牛客多校第七场E Find the median 离散化+线段树维护区间段

    Find the median 题意 刚开始集合为空,有n次操作,每次操作往集合里面插入[L[i],R[i]]的值,问每次操作后中位数是多少 分析 由于n比较大,并且数可以达到1e9,我们无法通过权值 ...

  3. 2019牛客多校第四场K number dp or 思维

    number 题意 给一个数字串,问有几个子串是300的倍数 分析 dp写法:这题一看就很dp,直接一个状态dp[i][j]在第i位的时候膜300的余数是j左过去即可.这题比赛的时候样例老是少1,后面 ...

  4. 线段树维护区间前k小

    线段树维护区间前k小 $ solution: $ 觉得超级钢琴太麻烦?在这里线段树提供一条龙服务 . 咳咳,开始讲正题!这道题我们有一个和超级钢琴复杂度一样 $ ~O(~\sum x\times lo ...

  5. 2020牛客多校第八场K题

    __int128(例题:2020牛客多校第八场K题) 题意: 有n道菜,第i道菜的利润为\(a_i\),且有\(b_i\)盘.你要按照下列要求给顾客上菜. 1.每位顾客至少有一道菜 2.给顾客上菜时, ...

  6. 【XSY2720】区间第k小 整体二分 可持久化线段树

    题目描述 给你你个序列,每次求区间第\(k\)小的数. 本题中,如果一个数在询问区间中出现了超过\(w\)次,那么就把这个数视为\(n\). 强制在线. \(n\leq 100000,a_i<n ...

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

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

  8. 左闭右开线段树 2019牛客多校(第七场)E_Find the median(点代表区间

    目录 题意 一种解析 AC_Code @(2019第七场牛客 E_Find the median 左闭右开线段树) 题意 链接:here 我理解的题意就是:初始序列为空,有\(n(400000)\)次 ...

  9. 【BZOJ3110】K大数查询(权值线段树套线段树+标记永久化,整体二分)

    题意:有N个位置,M个操作.操作有两种,每次操作 如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是 ...

随机推荐

  1. CentOS7下安装mysql5.1 或升级到5.7 以及小问题的解决方案

     正文开始 1.首先打开终端输入以下内容下载mysql5.1的repo源(安装5.7从第二步执行) wget http://repo.mysql.com/mysql-community-release ...

  2. HTML状态消息和方法

    参考链接1 参考链接2 当浏览器从 web 服务器请求服务时,可能会发生错误. HTML消息 1xx: 信息 消息: 描述: 100 Continue 服务器仅接收到部分请求,但是一旦服务器并没有拒绝 ...

  3. C++入门经典-例8.5-多重继承

    1:C++允许子类从多个父类继承公有的和受保护的成员,这称为多重继承. 2:多重继承的定义.多重继承有多个基类名称标识符,其声明形式如下: class 派生类名标识符:[继承方式] 基类名标识符1,. ...

  4. window 下要运行php,需要编辑php环境变量

    参考:https://blog.csdn.net/zhezhebie/article/details/72765262

  5. 再谈用Excel计算年龄

    有的时候,对于客人的信息并不是全知,那么身份证就可能用15位来代替,这个时候怎么计算年龄呢?有一个很简单的公式,可以一次性计算15位或18位身份证的年龄. 首先,需要判断一下,这个身份证是15位还是1 ...

  6. StringUtils字符串工具类左侧补齐(leftPad)、右侧补齐(rightPad)、左右两侧补齐(center)工具方法

    这里使用的是 org.apache.commons.lang.StringUtils;下面是StringUtils工具类中字符串左侧补齐的方法,示例如下: //左侧补齐 第一个参数:原始字符串,第二个 ...

  7. Bootstrap-CSS:目录

    ylbtech-Bootstrap-CSS:目录 1.返回顶部 1.   2. 2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部 1.   2.   6.返回顶部   7.返回顶部 ...

  8. backspace 产生乱码的问题

    1.要使用回删键(backspace)时,同时按住ctrl键(一般情况下会有用,如果没用使用下面的方法)   2.设定环境变量   在bash下:$ stty erase ^? 或者把 stty er ...

  9. NDk的目录

    * docs : 开发文档* build: linux下编译的批处理命令* platform : 某种平台下编译需要的头文件和函数库* prebuild : 预编译的工具* sample: 实例代码* ...

  10. 自定义View绘制简单的圆环的实现

    package com.loaderman.mywave; import android.content.Context; import android.graphics.Canvas; import ...