https://www.lydsy.com/JudgeOnline/problem.php?id=4071

https://www.luogu.org/problemnew/show/P3644

http://uoj.ac/problem/112

一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 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]巴邻旁之桥——题解的更多相关文章

  1. 【BZOJ4071】[Apio2015]巴邻旁之桥 Treap

    [BZOJ4071][Apio2015]巴邻旁之桥 Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 ...

  2. [bzoj4071] [Apio2015]巴邻旁之桥

    Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...

  3. 4071: [Apio2015]巴邻旁之桥

    Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...

  4. [APIO2015]巴邻旁之桥

    Bzoj权限题 luogu题面 先去掉同边的 首先k==1,即求一个点j 使\(\sum_{i\in A} |D_i - D_j| + \sum_{i\in B} |D_i - D_j|\)最小 因为 ...

  5. bzoj 4071: [Apio2015]巴邻旁之桥【splay】

    用权值线段树会容易一些并快一些,但是想复健一下splay所以打了splay 然后果然不会打了. 解题思路: 首先把家和办公室在同一侧的提出来直接加进答案里: 对于k=1,直接选所有办公室和家的中位数即 ...

  6. 洛谷 P3644 [APIO2015]八邻旁之桥 解题报告

    P3644 [APIO2015]八邻旁之桥 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好\(1000000001\)栋的建筑 ...

  7. [APIO2015]八邻旁之桥——非旋转treap

    题目链接: [APIO2015]八邻旁之桥 对于$k=1$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...

  8. 【BZOJ4071】【APIO2015】巴邻旁之桥

    题意: Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1 ...

  9. [BZOJ4071][APIO2015]八邻旁之桥

    BZOJ(这题是BZOJ权限题,有权限号的就去看看吧) Luogu(良心洛谷) 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好 ...

随机推荐

  1. 180709-Java实现获取本机Ip的工具类

    180709-Java实现获取本机Ip的工具类 获取本机Ip算是比较常见的一个需求场景了,比如业务报警,可能就会带上出问题的机器IP,方便直接上去看日志定位问题,那么问题来了,如何获取机器IP呢? I ...

  2. 怎样通过Qt编写C/C++代码查询当前Linux的版本号?

    遇到一个问题:如题. 我的开发环境是:嵌入式ARM + Linux系统 + Qt 4.5 + C/C++ 现在需要查询 当前Linux系统的版本号. 问题: 1)Qt 4.5 提供怎样的API来获取? ...

  3. 使用InstallShield-Limited-Edition制作安装包

    1.打开此网站,进行注册,获取序列码以及下载InstallShield-Limited-Edition 2.安装完成之后,打开VisualStudio,新建项目 3.填写基本应用信息 4.配置相关信息 ...

  4. @meida 媒体查询

    示例 @meida 媒体查询 在进行书写的时候需要考虑到加载顺序和样式权重使用meida响应式实现不同宽度布局示例 常用工具 https://mydevice.io 参考链接 https://deve ...

  5. springMVC第二章

    springMVC第二章 一.URL 映射 可以同时设置多个URL来访问某个控制器或方法.设置value属性: @RequestMapping(value= {"/grade",& ...

  6. kaldi HMM-GMM全部训练脚本分解

    目录 train_mono.sh train_deltas.sh train_lda_mllt.sh train_sat.sh train_mono.sh 单音素训练脚本: //初始化,[topo f ...

  7. CSS动画@-webkit-keyframes

    @-webkit-keyframes:以百分比来规定改变发生的时间,或者通过关键词 "from" 和 "to",等价于 0% 和 100%.0% 是动画的开始时 ...

  8. HADOOP docker(八):hadoop本地库

    前言2. Native Hadoop Library3. 使用本地库4. 本地库组件5. 支持的平台6. 下载7. 编译8. 运行时观察9. 检查本地库10. 如果共享本地库 小伙伴还记得每次启动hd ...

  9. POJ 3714 Raid(计算几何の最近点对)

    Description After successive failures in the battles against the Union, the Empire retreated to its ...

  10. 最全NB-IoT/eMTC物联网解决方案名录汇总

    NB-IoT/eMTC等蜂窝物联网技术的成熟和商用,占据低功耗广域网络(LPWAN)的主流地位,推动全球物联网新一轮发展热潮,越来越多的行业开始采用物联网方案来解决解决实际问题.实现落地应用,越来越多 ...