[bzoj4071] [Apio2015]巴邻旁之桥
Description
一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B。
每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1000000000。相邻的每对建筑相隔 1 个单位距离,河的宽度也是 1 个单位长度。区域 A 中的 i 号建筑物恰好与区域 B 中的 i 号建筑物隔河相对。
城市中有 N 个居民。第 i 个居民的房子在区域 Pi 的 Si 号建筑上,同时他的办公室坐落在 Qi 区域的 Ti 号建筑上。一个居民的房子和办公室可能分布在河的两岸,这样他就必须要搭乘船只才能从家中去往办公室,这种情况让很多人都觉得不方便。为了使居民们可以开车去工作,政府决定建造不超过 K 座横跨河流的大桥。
由于技术上的原因,每一座桥必须刚好连接河的两岸,桥梁必须严格垂直于河流,并且桥与桥之间不能相交。当政府建造最多 K 座桥之后,设 Di 表示第 i 个居民此时开车从家里到办公室的最短距离。请帮助政府建造桥梁,使得 D1+D2+⋯+DN 最小。
Input
输入的第一行包含两个正整数 K 和 N,分别表示桥的上限数量和居民的数量。
接下来 N 行,每一行包含四个参数:Pi,Si,Qi 和 Ti,表示第 i 个居民的房子在区域 Pi 的 Si 号建筑上,且他的办公室位于 Qi 区域的 Ti 号建筑上。
Output
输出仅为一行,包含一个整数,表示 D1+D2+⋯+DN 的最小值。
Sample Input
1 5
B 0 A 4
B 1 B 3
A 5 B 7
B 2 A 6
B 1 A 7
Sample Output
24
HINT
\(n\leqslant 10^5,k\in \{1,2\}\)。
Solution
在同侧的先预处理掉,过桥的\(1\)单位距离也预处理掉。
然后对于\(k=1\)的情况,桥显然要建在中位数上,\(splay\)维护下。
然后对于\(k=2\)的情况,显然有个断点,断点前的线段走第一座桥,断点后的线段走第二座桥,所以枚举断点,\(splay\)维护即可。
注意如果没有在河两侧的特判掉。
#include<bits/stdc++.h>
using namespace std;
#define int long long
void read(int &x) {
x=0;int f=1;char ch=getchar();
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
void print(int x) {
if(x<0) x=-x,putchar('-');
if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);puts("");}
const int maxn = 2e5+1;
int k,n,m,ans;
struct node {
int l,r;
bool operator < (const node &rhs) const {return (l+r)<(rhs.l+rhs.r);}
}a[maxn],b[maxn];
struct Splay_Tree {
int fa[maxn],son[maxn][2],sum[maxn],sz[maxn],val[maxn],rt,tot,cnt[maxn];
void update(int x) {
sum[x]=sum[son[x][0]]+sum[son[x][1]]+val[x]*cnt[x];
sz[x]=sz[son[x][0]]+sz[son[x][1]]+cnt[x];
}
int which(int x) {return son[fa[x]][1]==x;}
void rotate(int x) {
int f=fa[x],ff=fa[f],w=which(x);
if(ff) son[ff][son[ff][1]==f]=x;
fa[f]=x,fa[x]=ff,fa[son[x][w^1]]=f,son[f][w]=son[x][w^1],son[x][w^1]=f;
update(f),update(x);
}
void splay(int x) {
while(fa[x]) {
int y=fa[x],z=fa[y];
if(z) rotate(((son[y][1]==x)^(son[z][1]==y))?x:y);
rotate(x);
}update(x);rt=x;
}
int find(int x) {
int now=rt;
while(val[now]!=x) {
if(x<val[now]) {if(son[now][0]) now=son[now][0];else break;}
if(x>val[now]) {if(son[now][1]) now=son[now][1];else break;}
}
return now;
}
int newnode(int x) {val[++tot]=x,sz[tot]=cnt[tot]=1,sum[tot]=x;return tot;}
void insert(int x) {
if(!rt) return rt=newnode(x),void();
int now=find(x);
if(val[now]==x) return cnt[now]++,sz[now]++,splay(now),void();
son[now][val[now]<x]=newnode(x);fa[tot]=now;splay(now);
}
int kth(int kk) {
int now=rt;
while(1) {
if(kk<=sz[son[now][0]]) now=son[now][0];
else if(kk<=sz[son[now][0]]+cnt[now]) return now;
else kk-=sz[son[now][0]]+cnt[now],now=son[now][1];
}
}
int solve() {
int anss=0,now=kth(sz[rt]/2);splay(now);
anss=sz[son[rt][0]]*val[now]-sum[son[rt][0]]+sum[son[rt][1]]-sz[son[rt][1]]*val[now];
return anss;
}
}s,s2;
int res[maxn];
void solve() {
for(int i=1;i<=m;i++) {
s.insert(b[i].l),s.insert(b[i].r);
res[i]=s.solve();
}
if(k==1) return write(res[m]+ans);
int mn=1e18;
for(int i=m;i>=1;i--) {
s2.insert(b[i].l),s2.insert(b[i].r);
mn=min(mn,s2.solve()+res[i-1]);
}
write(mn+ans);
}
signed main() {
read(k),read(n);
for(int i=1;i<=n;i++) {
char s1[3],s3[3];
scanf("%s",s1+1),read(a[i].l),scanf("%s",s3+1),read(a[i].r);
if(s1[1]==s3[1]) ans+=abs(a[i].l-a[i].r);
else ans++,b[++m]=a[i];
}
if(!m) return write(ans),0;
sort(b+1,b+m+1);
solve();
return 0;
}
[bzoj4071] [Apio2015]巴邻旁之桥的更多相关文章
- 【BZOJ4071】[Apio2015]巴邻旁之桥 Treap
[BZOJ4071][Apio2015]巴邻旁之桥 Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 ...
- BZOJ4071 & 洛谷3644 & UOJ112:[APIO2015]巴邻旁之桥——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4071 https://www.luogu.org/problemnew/show/P3644 ht ...
- 4071: [Apio2015]巴邻旁之桥
Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...
- [BZOJ4071][APIO2015]八邻旁之桥
BZOJ(这题是BZOJ权限题,有权限号的就去看看吧) Luogu(良心洛谷) 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好 ...
- [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\)栋的建筑 ...
- 【BZOJ4071】八邻旁之桥(线段树)
[BZOJ4071]八邻旁之桥(线段树) 题面 BZOJ权限题,洛谷链接 题解 既然\(k<=2\) 那么,突破口就在这里 分类讨论 ①\(k=1\) 这...不就是中位数吗.... 直接把所有 ...
- [APIO2015]八邻旁之桥——非旋转treap
题目链接: [APIO2015]八邻旁之桥 对于$k=1$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...
随机推荐
- Layabox进阶之资源加载
资源加载失败,图片资源默认类型是image 如果是sprite可能找不到. 资源的加载顺序,场景被加载出来时,要判断该场景的资源是否都已经加载到. 点击A界面弹出来B界面,A界面的资源要在B界面之前加 ...
- MySQL必会
SQL语言对大小写不敏感,但一般使用大.1.创建数据库 CREATE DATABASE test; 2.授予权限 CRANT ALL ON test.* to user(s); 3.使用指定数据库 U ...
- CDSビュー新規作成
CDSビューの追加文書いついては以下の内容も参照してください. ABAP keyword documentation SAP Community. Step 1: CDSビュー作成 Favorite ...
- Django学习之天气调查实例(3):部署静态文件CSS、JS、images等(部署环境基于Ubuntu)
在设计登录界面时,采用了网上下载的登录模板,漂亮,简易.但是在测试和部署时,发现原来模板中采用的js文件和css文件,却着实让我折腾了好几天. 在以往的网页设计中,一般只要把测试站点开启后,网页中的静 ...
- 【转】已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭
在运用Linq to sql 或者 linq to entity等相关linq技术进行数据库访问操作时,如果发生上述异常是因为是因为.NET內部是使用DataReader作数据存取,DataReade ...
- 新版IdFTP解决中文乱码问题
用XE10后开发FTP客户端,发现有中文乱码问题.这里也主要是编码的问题,在connect链接后,需要设置编码方可. 注意: IndyTextEncoding_OSDefault; 该代码可能需 ...
- LeetCode:21. Merge Two Sorted Lists(Easy)
1. 原题链接 https://leetcode.com/problems/merge-two-sorted-lists/description/ 2. 题目要求 给出两个已经从小到大排序的链表ls1 ...
- 源码解析:解析掌阅X2C 框架
前言 掌阅出品了X2C 框架,听说可以加快性能.喜欢研究源码的我,肯定要来看下是怎么回事. 作为一个开发,应该不屑于只会使用开源框架. OK,来尝试下. 项目地址: https://github.co ...
- 云计算之路-阿里云上:原来“黑色0.1秒”发生在socket读取数据时
在昨天的博文(云计算之路-阿里云上:读取缓存时的“黑色0.1秒”)中我们犯了一个很低级的错误——把13ms算成了130ms(感谢陈硕发现这个错误!),从而对问题的原因作出了错误的推断,望大家谅解! 从 ...
- 【SpringCloud】第一篇: 服务的注册与发现(Eureka)
前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...