当前位置: 首页 > news >正文

BZOJ4071 洛谷3644 UOJ112:[APIO2015]巴邻旁之桥——题解

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=200100;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
inline char getc(){
    char ch=0;
    while(ch!='A'&&ch!='B')ch=getchar();
    return ch;
}
struct node{
    int l,r;
}q[N];
int m,tot,b[N];
ll num[2][N*4],sum[2][N*4],L[2],R[2];
bool cmp(node a,node b){return a.l+a.r<b.l+b.r;}
void LSH(){
    sort(b+1,b+m+1);
    m=unique(b+1,b+m+1)-b-1;
    for(int i=1;i<=tot;i++){
    q[i].l=lower_bound(b+1,b+m+1,q[i].l)-b;
    q[i].r=lower_bound(b+1,b+m+1,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)>>1;
    if(k<=mid)insert(a*2,l,mid,k,w,p);
    else insert(a*2+1,mid+1,r,k,w,p);
}
int find(int a,int l,int r,int k,int p){
    if(l==r){
    L[0]+=sum[p][a],L[1]+=num[p][a];
    return b[l];
    }
    int mid=(l+r)>>1;
    if(num[p][a*2]>=k){
    R[0]+=sum[p][a*2+1],R[1]+=num[p][a*2+1];
    return find(a*2,l,mid,k,p);
    }else{
    L[0]+=sum[p][a*2],L[1]+=num[p][a*2];
    return find(a*2+1,mid+1,r,k-num[p][a*2],p);
    }
}
int main(){
    int k=read(),n=read();
    ll ans=0;
    for(int i=1;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==2){
        q[++tot]=(node){u,v};
        }
    }
    if(k==1){
        sort(b+1,b+m+1);
        for(int i=1,j=m;i<j;i++,j--)ans+=b[j]-b[i];
        printf("%lld\n",ans);
    }else{
    if(!tot){
        printf("%lld\n",ans);
        return 0;
    }
        sort(q+1,q+tot+1,cmp);
    LSH();
    for(int i=1;i<=tot;i++){
        insert(1,1,m,q[i].l,1,1);
        insert(1,1,m,q[i].r,1,1);
    }
    int x=find(1,1,m,tot,1);
    ll tmp=x*L[1]-L[0]+R[0]-x*R[1];
    for(int i=1;i<tot;i++){
        insert(1,1,m,q[i].l,1,0);
        insert(1,1,m,q[i].r,1,0);
        insert(1,1,m,q[i].l,-1,1);
        insert(1,1,m,q[i].r,-1,1);
        ll all=0;
        L[0]=L[1]=R[0]=R[1]=0;
        x=find(1,1,m,i,0);
        all+=x*L[1]-L[0]+R[0]-x*R[1];
        L[0]=L[1]=R[0]=R[1]=0;
        x=find(1,1,m,tot-i,1);
        all+=x*L[1]-L[0]+R[0]-x*R[1];
        tmp=min(tmp,all);
    }
    printf("%lld\n",ans+tmp);
    }
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

转载于:https://www.cnblogs.com/luyouqi233/p/8669351.html

相关文章:

  • xtrabackup 在线主从搭建
  • css3实现渐变
  • 泼出去的“邮件”U-Mail邮件系统替你收回
  • 1036. [ZJOI2008]树的统计【树链剖分】
  • Koa2 之文件上传下载
  • BZOJ1010:[HNOI2008]玩具装箱TOY(斜率优化DP)
  • 黑客基础之 DOS命令3
  • postgreSQL中如何实现group_concat
  • Linux系统获取命令帮助方法及简单命令介绍
  • ★ prototype、__proto__ 详解
  • 大数据生态圈的一致性
  • Java 8 并发篇 - 冷静分析 Synchronized(上)
  • 运维面试题
  • react-router了解一下
  • 狼叔:Node全栈为前端带来更多可能
  • 「译」Node.js Streams 基础
  • Angular 响应式表单 基础例子
  • Git同步原始仓库到Fork仓库中
  • js继承的实现方法
  • Map集合、散列表、红黑树介绍
  • 规范化安全开发 KOA 手脚架
  • 聊聊sentinel的DegradeSlot
  • 前端技术周刊 2019-02-11 Serverless
  • 入手阿里云新服务器的部署NODE
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • 优秀架构师必须掌握的架构思维
  • 走向全栈之MongoDB的使用
  • RDS-Mysql 物理备份恢复到本地数据库上
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • #AngularJS#$sce.trustAsResourceUrl
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • (11)工业界推荐系统-小红书推荐场景及内部实践【粗排三塔模型】
  • (2)(2.10) LTM telemetry
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (C语言)字符分类函数
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (算法)Travel Information Center
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .gitignore文件_Git:.gitignore
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .NET序列化 serializable,反序列化
  • .NET业务框架的构建
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • @transaction 提交事务_【读源码】剖析TCCTransaction事务提交实现细节
  • [2018-01-08] Python强化周的第一天
  • [ACTF2020 新生赛]Upload 1
  • [AutoSAR系列] 1.3 AutoSar 架构
  • [Docker]五.Docker中Dockerfile详解
  • [HDU5685]Problem A
  • [iOS]-UIKit
  • [Java][方法引用]构造方法的引用事例分析
  • [leetcode] 61. 旋转链表