kick start 2019 round D T3题解
---恢复内容开始---
题目大意:共有N个房子,每个房子都有各自的坐标X[i],占据每个房子需要一定花费C[i]。现在需要选择K个房子作为仓库,1个房子作为商店(与题目不同,概念一样),由于仓库到房子之间存在距离 | Xi-Xj | ,所以想要使“占据K+1个房子以及每个仓库到商店的距离和”最小化,并输出该最小值。
数据范围:K<N<=1e5,C[i],X[i]<=1e9。
解题思路:比赛期间使用的是N*N*log(N)的时间复杂度,总体思路是先选定商店位置,再将其他房子按照“花费+距离”进行快排,选出前K优的房子作为仓库。理想的时间复杂度是N*log(K)的,在看过题解后着实佩服google的题……曾经有人分我说过google出的题要是你没做出来,你也是心服口服的,现在我真的意识到了。
改解法依旧将问题剖解,首先是一个老生常谈的问题:如果已经选好了K+1个房子,那么商店放在哪合适?这是以往的基础题了,最后的结论是房子位置的中位数处。有了这样的概念后,在枚举商店时,就可以确认商店左右(关于X的左右)两边各有K/2间仓库(可能出现奇偶问题,大家可以自己想想)。于是来到下一个子问题:如何获得一个商店左侧C[i]-X[i]最小的K/2个值的和呢(这句话大家也可以想想),又如何获得一个商店右侧C[i]+X[i]最小的K-K/2个值的和呢?
这两个问题是强关联的(我最开始没发现。。真是傻),可以利用最大堆解决,以左侧为例,先将以X排序好的房子#1~#K/2的C[i]-X[i]值加入最大堆,并记录当前最值的最大堆所有元素和。当对#K/2+1~#N的房子依次进行分析时,首先看当前房间的C[i]-X[i]值是否小于最大堆的top值,若小于,则更新最大堆(弹出top,压入c[i]-x[i])与元素和。
维护好suml[]以及sumr[]两数组后,就可以枚举商店位置,计算以此处为商店的租界最小值,再将每个商店的租界最小值取最小值,即可得到答案。
语义不清。。有空再回顾一下重写吧。真是好题。
最终代码:
#include <stdio.h>
#include <queue>
#include <algorithm>
using namespace std; priority_queue<long long> qq;
struct ooo{
int xx,cc;
}hou[];
bool cmp(ooo a,ooo b){
return a.xx<b.xx;
}
int x[],c[];
long long suml[],sumr[];
int mainn()
{
int k,n;scanf("%d%d",&k,&n);
for (int i=;i<=n;i++) scanf("%d",&hou[i].xx);
for (int i=;i<=n;i++) scanf("%d",&hou[i].cc);
sort(hou+,hou+n+,cmp);
for (int i=;i<=n;i++)
{
x[i]=hou[i].xx;c[i]=hou[i].cc;
}
while (!qq.empty()) qq.pop();
suml[]=;
for (int i=;i<=n;i++)
{
if (k==)
{
suml[i]=;
continue;
}
if (i<=k/)
{
suml[i]=suml[i-]+c[i]-x[i];
qq.push(c[i]-x[i]);
continue;
}
if( c[i]-x[i] < qq.top() ){
suml[i]=suml[i-]-qq.top();
qq.pop();
qq.push(c[i]-x[i]);
suml[i]+=(c[i]-x[i]);
}
else
suml[i]=suml[i-];
}
while (!qq.empty()) qq.pop();
sumr[n+]=;
for (int i=n;i>;i--)
{
if ( qq.size()<k-k/ )
{
sumr[i]=sumr[i+]+c[i]+x[i];
qq.push(c[i]+x[i]);
continue;
}
if (c[i]+x[i]<qq.top() ){
sumr[i]=sumr[i+]-qq.top();
qq.pop();
qq.push(c[i]+x[i]);
sumr[i]+=(c[i]+x[i]);
}
else
sumr[i]=sumr[i+];
}
long long ans=-;
for (int i=k/+;i+k-k/<=n;i++)
{
long long tmp=c[i]+suml[i-]+sumr[i+];
if (k%) tmp-=x[i];
if (ans==- || ans>tmp)
ans=tmp;
}
printf(" %lld\n",ans);
//for (int i=1;i<=n;i++)
// printf("%lld %lld\n",suml[i],sumr[i]); } int main()
{
int T;scanf("%d",&T);
for (int i=;i<=T;i++)
{
printf("Case #%d:",i);
mainn();
}
}
题目链接:
https://codingcompetitions.withgoogle.com/kickstart/round/0000000000051061/0000000000161476
kick start 2019 round D T3题解的更多相关文章
- kick start 2019 round D T2题解
题目大意:由N个房子围成一个环,G个人分别顺时针/逆时针在房子上走,一共走M分钟,每分钟结束,每个人顺/逆时针走到相邻的房子.对于每个房子都会记录最后时刻到达的人(可能是一群人).最终输出每个人会被几 ...
- [多校联考2019(Round 5 T3)]青青草原的表彰大会(dp+组合数学)
[多校联考2019(Round 5)]青青草原的表彰大会(dp+组合数学) 题面 青青草原上有n 只羊,他们聚集在包包大人的家里,举办一年一度的表彰大会,在这次的表彰大会中,包包大人让羊们按自己的贡献 ...
- Kick Start 2019 Round A Contention
$\DeclareMathOperator*{\argmax}{arg\,max}$ 题目链接 题目大意 一排 $N$ 个座位,从左到右编号 $1$ 到 $N$ . 有 $Q$ 个预定座位的请求,第 ...
- Kick Start 2019 Round H. Elevanagram
设共有 $N = \sum_{i=1}^{9} A_i$ 个数字.先把 $N$ 个数字任意分成两组 $A$ 和 $B$,$A$ 中有 $N_A = \floor{N/2}$ 个数字,$B$ 中有 $N ...
- 【DP 好题】Kick Start 2019 Round C Catch Some
题目链接 题目大意 在一条数轴上住着 $N$ 条狗和一个动物研究者 Bundle.Bundle 的坐标是 0,狗的坐标都是正整数,可能有多条狗住在同一个位置.每条狗都有一个颜色.Bundle 需要观测 ...
- Kick Start 2019 Round A Parcels
题目大意 $R \times C$ 的网格,格子间的距离取曼哈顿距离.有些格子是邮局.现在可以把至多一个不是邮局的格子变成邮局,问每个格子到最近的邮局的曼哈顿距离的最大值最小是多少. 数据范围 $ 1 ...
- Kick Start 2019 Round B Energy Stones
对我很有启发的一道题. 这道题的解法中最有思维难度的 observation 是 For simplicity, we will assume that we never eat a stone wi ...
- Kick Start 2019 Round F Teach Me
题目链接 题目大意 有 $N$ 个人,$S$ 项技能,这些技能用 $1, 2, 3, \dots, S$ 表示 .第 $i$ 个人会 $c_i$ 项技能($ 1 \le c_i \le 5 $).对于 ...
- Kick Start 2019 Round D
X or What? 符号约定: $\xor$ 表示异或. popcount($x$) 表示非负整数 $x$ 的二进制表示里数字 1 出现的次数.例如,$13 = 1101_2$,则 popcount ...
随机推荐
- MOCTF-Crypt-writeup
MOctf Crypt Writeup记录 都不难,就随便记录记录下. MOCTF平台地址:http://www.moctf.com 0x01 数据库密码 hint:20岁的小刚,自幼热爱信息安全,一 ...
- 封装 Gson 解析Json到对象是否失败
在使用Google的 Gson 类库解析 Json 数据时,难免会出现解析失败的情况. 在这种情况下,使用 if(obj == null) 是不可行的,fromJson 方法会自动生成对象的实例,所以 ...
- Netty学习(六)-LengthFieldBasedFrameDecoder解码器
在TCP协议中我们知道当我们在接收消息时候,我们如何判断我们一次读取到的包就是整包消息呢,特别是对于使用了长连接和使用了非阻塞I/O的程序.上节我们也说了上层应用协议为了对消息进行区分一般采用4种方式 ...
- 假装前端工程师(一)Icework + GitHub pages 快速构建可自定义迭代开发的 react 网站
icework + gh-pages 超快部署超多模版页面 项目地址:https://github.com/yhyddr/landingpage效果地址:https://yhyddr.github.i ...
- RocketMQ中PullConsumer的启动源码分析
通过DefaultMQPullConsumer作为默认实现,这里的启动过程和Producer很相似,但相比复杂一些 [RocketMQ中Producer的启动源码分析] DefaultMQPullCo ...
- 【openmp】for循环的break问题
问题描述:在用openmp并行化处理for循环的时候,便无法在for循环中用break语句,那么我们如何实现这样的机制呢?在stackoverflow上看到一个不错的回答总结一下. volatile ...
- 记录一次Git解决CONFLICT冲突
目录 记录一次Git解决CONFLICT冲突 1.CONFLICT产生的原因 2.Git正确的LIANGZHONG 使用流程 2.1 暂存,拉取,恢复暂存,合并(如果有冲突),提交,推送 2.2 将本 ...
- win10下vc++6.0的安装问题
由于最近需要在win10系统下用到vc++来编程(其实刚开始我是拒绝的,因为vc++各种坑),下面我就把安装vc++时遇到的问题记录下来,方便以后同样遇到这些问题的同学. 安装vc++6.0所需要东西 ...
- 【JavaScript】论一个低配版Web实时通信库是如何实现的之二( EventSource篇)
前情提要 「 话说上回说到!那WebSocket大侠,巧借http之内力,破了敌阵的双工鸳鸯锁,终于突出重围. 然而玄难未了,此时web森林中飞出一只银头红缨枪,划破夜色. "莫非!?&qu ...
- aabccd统计每个字符出现的次数,结果显示{ a: 2, b: 1, c: 2, d: 1 };去掉重复的字符,使结果显示abcd
遍历字符串的方式和遍历数组的方式有点相似,或者说就是相同的.在学习数组的遍历方法之前,可以通过for循环去遍历数组,同样,字符串也可以:字符串跟数组都有一个length的属性.下面代码奉上,个人思路! ...