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. 「功能笔记」性能分析工具gprof使用笔记

    根据网上信息整理所成. 功能与优劣 gprof实际上只是一个用于读取profile结果文件的工具.gprof采用混合方法来收集程序的统计信息,它使用检测方法,在编译过程中在函数入口处插入计数器用于收集 ...

  2. 爬虫初体验:Python+Requests+BeautifulSoup抓取广播剧

    可以看到一个DIV下放一个广播剧的信息,包括名称和地址,第一步我们先收集所有广播剧的收听地址: # 用requests的get方法访问novel_list_resp = requests.get(&q ...

  3. python3爬虫-快速入门-爬取图片和标题

    直接上代码,先来个爬取豆瓣图片的,大致思路就是发送请求-得到响应数据-储存数据,原理的话可以先看看这个 https://www.cnblogs.com/sss4/p/7809821.html impo ...

  4. Paper Reading - CNN+CNN: Convolutional Decoders for Image Captioning

    Link of the Paper: https://arxiv.org/abs/1805.09019 Innovations: The authors propose a CNN + CNN fra ...

  5. HADOOP docker(二):HDFS 高可用原理

        1.环境简述2.QJM HA简述2.1为什么要做HDFS HA?2.2 HDFS HA的方式2.2 HSFS HA的结构2.3 机器要求3.部署HDFS HA3.1 详细配置3.2 部署HDF ...

  6. [C++] OOP - Base and Derived Classes

    There is a base class at the root of the hierarchy, from which the other class inherit, directly or ...

  7. POJ 3304 Segments(线的相交判断)

    Description Given n segments in the two dimensional space, write a program, which determines if ther ...

  8. Greedy Gift Givers 贪婪的送礼者

    Description 对于一群要互送礼物的朋友,TRW要确定每个人送出的钱比收到的多多少.在这一个问题中,每个人都准备了一些钱来送礼物,而这些钱将会被平均分给那些将收到他的礼物的人.然而,在任何一群 ...

  9. wwnjld团队第二轮迭代成员分数

    2014-01-05 第二轮迭代团队内成员分数如下(依据分数分配规则以及团队会议协商所得结果): 吴渊渊 23 汪仁贵 21.5 高小洲 19.5 聂建 22.5 吕家辉 23.5 程志 10

  10. iOS开发解决页面滑动返回跟scrollView左右划冲突

    -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithG ...