BZOJ4071 & 洛谷3644 & UOJ112:[APIO2015]巴邻旁之桥——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4071
https://www.luogu.org/problemnew/show/P3644
一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B。
每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000。相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度。区域 A 中的 i 号建筑物恰好与区域 B 中的 i 号建筑物隔河相对。城市中有 N 个居民。第 i 个居民的房子在区域 Pi 的 Si 号建筑上,同时他的办公室坐落在 Qi 区域的 Ti 号建筑上。一个居民的房子和办公室可能分布在河的两岸,这样他就必须要搭乘船只才能从家中去往办公室,这种情况让很多人都觉得不方便。为了使居民们可以开车去工作,政府决定建造不超过 K 座横跨河流的大桥。由于技术上的原因,每一座桥必须刚好连接河的两岸,桥梁必须严格垂直于河流,并且桥与桥之间不能相交。当政府建造最多 K 座桥之后,设 Di 表示第 i 个居民此时开车从家里到办公室的最短距离。请帮助政府建造桥梁,使得 D1+D2+⋯+DN 最小。
参考:https://www.cnblogs.com/zhenghaotian/p/8304917.html
对于同岸和走桥的代价先预处理,下面不在阐述。
k=1时,相当于找到一个点,使得所有起点和终点到该点的距离和最小。则我们排序在中间两点中间建桥则一定最优。就不证明了。
k=2时不能按k=1做(因为起点和终点需要用的桥是一样的),但是选桥的代价为(A起点,B桥,C终点)A->B->C,显然选一个近的桥最优,用程序表达的话就是离AC中点最近的桥。
所以以此排序,枚举分界点,其左右都是k=1的情况,用线段树做即可。
(简单聊下心路历程:开始k=1秒后想k=2,没考虑起点终点桥一样以为三分可过,结果第二个样例就跪了,后来思考之后排序后三分是O(nlog^2n)结果洛谷评测机死活没卡过去TAT果然还是太菜了我)
- #include<cstdio>
- #include<queue>
- #include<cctype>
- #include<cstring>
- #include<cmath>
- #include<vector>
- #include<algorithm>
- using namespace std;
- typedef long long ll;
- const int N=;
- inline int read(){
- int X=,w=;char ch=;
- while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
- while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
- return w?-X:X;
- }
- inline char getc(){
- char ch=;
- while(ch!='A'&&ch!='B')ch=getchar();
- return ch;
- }
- struct node{
- int l,r;
- }q[N];
- int m,tot,b[N];
- ll num[][N*],sum[][N*],L[],R[];
- bool cmp(node a,node b){return a.l+a.r<b.l+b.r;}
- void LSH(){
- sort(b+,b+m+);
- m=unique(b+,b+m+)-b-;
- for(int i=;i<=tot;i++){
- q[i].l=lower_bound(b+,b+m+,q[i].l)-b;
- q[i].r=lower_bound(b+,b+m+,q[i].r)-b;
- }
- }
- void insert(int a,int l,int r,int k,ll w,int p){
- num[p][a]+=w,sum[p][a]+=w*b[k];
- if(l==r)return;
- int mid=(l+r)>>;
- if(k<=mid)insert(a*,l,mid,k,w,p);
- else insert(a*+,mid+,r,k,w,p);
- }
- int find(int a,int l,int r,int k,int p){
- if(l==r){
- L[]+=sum[p][a],L[]+=num[p][a];
- return b[l];
- }
- int mid=(l+r)>>;
- if(num[p][a*]>=k){
- R[]+=sum[p][a*+],R[]+=num[p][a*+];
- return find(a*,l,mid,k,p);
- }else{
- L[]+=sum[p][a*],L[]+=num[p][a*];
- return find(a*+,mid+,r,k-num[p][a*],p);
- }
- }
- int main(){
- int k=read(),n=read();
- ll ans=;
- for(int i=;i<=n;i++){
- char ch1=getc();
- ll u=read();
- char ch2=getc();
- ll v=read();
- if(ch1==ch2){
- ans+=abs(u-v);
- continue;
- }
- ans++;
- b[++m]=u,b[++m]=v;
- if(k==){
- q[++tot]=(node){u,v};
- }
- }
- if(k==){
- sort(b+,b+m+);
- for(int i=,j=m;i<j;i++,j--)ans+=b[j]-b[i];
- printf("%lld\n",ans);
- }else{
- if(!tot){
- printf("%lld\n",ans);
- return ;
- }
- sort(q+,q+tot+,cmp);
- LSH();
- for(int i=;i<=tot;i++){
- insert(,,m,q[i].l,,);
- insert(,,m,q[i].r,,);
- }
- int x=find(,,m,tot,);
- ll tmp=x*L[]-L[]+R[]-x*R[];
- for(int i=;i<tot;i++){
- insert(,,m,q[i].l,,);
- insert(,,m,q[i].r,,);
- insert(,,m,q[i].l,-,);
- insert(,,m,q[i].r,-,);
- ll all=;
- L[]=L[]=R[]=R[]=;
- x=find(,,m,i,);
- all+=x*L[]-L[]+R[]-x*R[];
- L[]=L[]=R[]=R[]=;
- x=find(,,m,tot-i,);
- all+=x*L[]-L[]+R[]-x*R[];
- tmp=min(tmp,all);
- }
- printf("%lld\n",ans+tmp);
- }
- return ;
- }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
BZOJ4071 & 洛谷3644 & UOJ112:[APIO2015]巴邻旁之桥——题解的更多相关文章
- 【BZOJ4071】[Apio2015]巴邻旁之桥 Treap
[BZOJ4071][Apio2015]巴邻旁之桥 Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 ...
- [bzoj4071] [Apio2015]巴邻旁之桥
Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...
- 4071: [Apio2015]巴邻旁之桥
Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...
- [APIO2015]巴邻旁之桥
Bzoj权限题 luogu题面 先去掉同边的 首先k==1,即求一个点j 使\(\sum_{i\in A} |D_i - D_j| + \sum_{i\in B} |D_i - D_j|\)最小 因为 ...
- bzoj 4071: [Apio2015]巴邻旁之桥【splay】
用权值线段树会容易一些并快一些,但是想复健一下splay所以打了splay 然后果然不会打了. 解题思路: 首先把家和办公室在同一侧的提出来直接加进答案里: 对于k=1,直接选所有办公室和家的中位数即 ...
- 洛谷 P3644 [APIO2015]八邻旁之桥 解题报告
P3644 [APIO2015]八邻旁之桥 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好\(1000000001\)栋的建筑 ...
- [APIO2015]八邻旁之桥——非旋转treap
题目链接: [APIO2015]八邻旁之桥 对于$k=1$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...
- 【BZOJ4071】【APIO2015】巴邻旁之桥
题意: Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1 ...
- [BZOJ4071][APIO2015]八邻旁之桥
BZOJ(这题是BZOJ权限题,有权限号的就去看看吧) Luogu(良心洛谷) 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好 ...
随机推荐
- xencenter迁移云主机方法
问题:POOL中计算节点内存不足. 解决方法:1.为计算节点添加内存(费用高)2.将部分资源迁移到其它POOL中. 方法: 1.选择要迁移的虚拟机 2.选择保存路径 这里可以看到可以批量导出: 注意: ...
- MaxScript代码补全插件
MaxScript代码补全插件 作者Nik,原文发布于ScriptSpot 安装后max自带脚本编辑器会有自动补全,效果如下:
- Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis
第5章--MyBatis MyBatis入门 Abstract: 数据库框架的工作原理和使用方法(以MyBatis为例) 面向对象的世界与关系型数据库的鸿沟: 面向对象世界中的数据是对象: 关系型数据 ...
- 看图写树 (Undraw the Trees UVA - 10562)
题目描述: 原题:https://vjudge.net/problem/UVA-10562 题目思路: 递归找结点 //自己的代码测试过了,一直WA,贴上紫书的代码 AC代码 #include< ...
- 爬虫1.5-ajax数据爬取
目录 爬虫-ajax数据爬取 1. ajax数据 2. selenium+chromedriver知识准备 3. selenium+chromedriver实战拉勾网爬虫代码 爬虫-ajax数据爬取 ...
- 数据库Mysql的学习(五)-运算符与函数
,store,store,store,store FROM bookinfo;//加减乘除取余 //余额大于200 //余额不等于200 SELECT * FROM readerinfo WHERE ...
- Vuejs 基础与语法
Vue 实例 创建第一个实例 {{}} 被称之为插值表达式.可以用来进行文本插值. <!DOCTYPE html> <html lang="en"> < ...
- Shell 常用命令、基本用法总结
Filter Filter 常用于从大量文本.数据中提取需求的部分.下面介绍几个常用的 filter 命令. cut $ cut -c 5-8 textfile.txt # 切出 textfile.t ...
- /etc/fstab 文件如何填写(转)
转载自 http://hi.baidu.com/jingzhongchen/blog/item/8e6f552dcead7ce98b139952.html 看你对/etc/fstab文件了解多少? ...
- Python中的__future__
在Python中,你如果在某一个版本的Python想使用未来版本中的功能,可以使用如下语法实现: from __future__ import futurename 这条语句必须放在module文件的 ...