题目链接: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. Python基础之Python解释器

    当我们在编写Python代码时,我们得到的是一个包含Python代码的,以.py为扩展名的文本文件.要运行代码,就需要Python解释器去执行.py文件. 由于整个Python语言从规范到解释器都是开 ...

  2. AtCoder AGC032E Modulo Pairing (二分、贪心与结论)

    题目链接 https://atcoder.jp/contests/agc032/tasks/agc032_e 题解 猜结论好题. 结论是: 按\(a_i\)从小到大排序之后,一定存在一种最优解,使得以 ...

  3. Oracle For Linux

    安装前检查 检查是否安装以下软件rpm -qa | grep **下面**软件包 安装包名称 是否安装 binutils-2.17.50.0.6 √ compat-libstdc++-33-3.2. ...

  4. CLion配置Cygwin环境

    CLion "download" 跳转到 https://cygwin.com/install.html 下载64位安装程序并安装 国内添加网易镜像 http://mirrors. ...

  5. (九)C语言之scanf

  6. javascript中“use strict”的好处和坏处

    1.为什么使用严格模式? 消除javascript语法的一些不合理.不严谨之处,减少一些怪异行为: 消除代码运行的不安全之处,保证代码的运行: 提高编译效率,增加运行效率: 为未来新版本的javasc ...

  7. beta 2/2 阶段中间产物提交入口

    此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/9961 组名:胜利点 组长:贺敬文 队员:位军营,徐丽君,彭思雨,王志文 g ...

  8. cin.clear()与cin.sync()的使用

    cin.clear()与cin.sync()使用是有先后顺序的. 他们的作用: cin.clear(); //将流中的所有状态都重设为有效值 cin.sync();//清空流 在输入错误的情况下,如果 ...

  9. 安装指定版本的Ionic或Cordova

    安装ionic 及 cordova npm install -g cordova ionic更新命令 npm update -g cordova ionic安装特定版本 npm install -g ...

  10. ajax-php跨域请求

    php: function __construct(){ // 指定允许其他域名访问 header("Access-Control-Allow-Origin: *"); heade ...