BZOJ(这题是BZOJ权限题,有权限号的就去看看吧)

Luogu(良心洛谷)

题目描述

一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\)。

每一块区域沿着河岸都建了恰好\(1000000001\)栋的建筑,每条岸边的建筑都从\(0 编号到 1000000000\)。相邻的每对建筑相隔\(1\)个单位距离,河的宽度也是\(1\)个单位长度。区域\(A\)中的\(i\)号建筑物恰好与区域\(B\)中的\(i\)号建筑物隔河相对。

城市中有\(N\)个居民。第\(i\)个居民的房子在区域\(P_i\)的\(S_i\)号建筑上,同时他的办公室坐落在\(Q_i\)区域的\(T_i\)号建筑上。一个居民的房子和办公室可能分布在河的两岸,这样他就必须要搭乘船只才能从家中去往办公室,这种情况让很多人都觉得不方便。为了使居民们可以开车去工作,政府决定建造不超过\(K\)座横跨河流的大桥。

由于技术上的原因,每一座桥必须刚好连接河的两岸,桥梁必须严格垂直于河流,并且桥与桥之间不能相交。

当政府建造最多\(K\)座桥之后,设\(D_i\)表示第\(i\)个居民此时开车从家里到办公室的最短距离。请帮助政府建造桥梁,使得 \(D1+D2+⋯+DN\)最小。

输入格式:

输入的第一行包含两个正整数\(K\)和\(N\),分别表示桥的上限数量和居民的数量。

接下来\(N\)行,每一行包含四个参数:\(P_i,S_i,Q_i\)和\(T_i\),表示第\(i\)个居民的房子在区域\(P_i\)的\(S_i\)号建筑上,且他的办公室位于\(Q_i\)区域的\(T_i\)号建筑上。

输出格式:

输出仅为一行,包含一个整数,表示\(D1+D2+⋯+DN\)的最小值.

输入样例#1:

1 5
B 0 A 4
B 1 B 3
A 5 B 7
B 2 A 6
B 1 A 7

输出样例#1:

24

输入样例#2:

2 5
B 0 A 4
B 1 B 3
A 5 B 7
B 2 A 6
B 1 A 7

输出样例#2:

22

说明

所有数据都保证:\(P_i\) 和 \(Q_i\) 为字符 \(“A”\) 和 \(“B”\) 中的一个, \(0≤S_i,T_i≤10000000000\) ,同一栋建筑内可能有超过 \(1\) 间房子或办公室(或二者的组合,即房子或办公室的数量同时大于等于 \(1\))。

子任务 1 (8 分)\(K=1\quad1≤N≤1000\)

子任务 2 (14 分)\(K=1\quad1≤N≤100000\)

子任务 3 (9 分)\(K=2\quad1≤N≤100\)

子任务 4 (32 分)\(K=2\quad1≤N≤1000\)

子任务 5 (37 分)\(K=2\quad1≤N≤100000\)

sol

这题看上去很不可做呀,但是很明显\(K≤2\)这个条件是非常重要的。

先考虑\(K=1\)怎么做。

首先,如果一个人的房子和办公室位于河的同一侧,那么这个人肯定是不受任何影响的,即他对答案的贡献永不变。我们先把这种人预处理了,然后剩下的全是必须要过河的。

那么现在有\(cnt\)个人要过河,第\(i\)个人要从\(A_i\)走到\(B_i\),或者说,从\(A_i\)走到桥的位置\(pos\),再从桥的位置\(pos\)走到\(B_i\)。说白了我们就是要求\(\sum abs(A_i-pos)+abs(B_i-pos)\),可发现\(A_i\)与\(B_i\)其实无差别。

所以就把所有的\(A_i\)跟\(B_i\)放在一起排序,然后桥的位置就一定是排序后中位数的位置。暴力统计每个点到桥的距离,这样\(K=1\)就做完了。

现在来考虑\(K=2\)。

首先看这样一个结论:对每个人来说,他一定会走那座离\((A_i+B_i)/2\)更近的桥。这个结论其实不需要证明,手玩一下即可。

那么我们把所有人按照\((A_i+B_i)/2\)排序,那么一定是左边一部分人走左边的那座桥,右边的一部分人走右边的那座桥。

所以我们要对左右分别维护一个数据结构,支持快速插入、删除元素,并可以快速查询中位数、查询区间和。在这里splay和权值线段树都是不错的选择。

那么这题就做完啦。嗯哼。

code

本代码使用权值线段树。

本代码使用cin读入数据。

#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N = 100005;
struct node{
int u,v;
bool operator < (const node &b) const
{return u+v<b.u+b.v;}
}x[N];
int n,k,a,b,o[N<<1],len,sz[2][N<<3],cnt;
ll useless,tot1,tot2,sum[2][N<<3],ans;
char op1,op2;
void work1()
{
for (int i=1;i<=n;i++)
{
cin>>op1>>a>>op2>>b;
if (op1==op2) useless+=abs(a-b);
else useless++,o[++len]=a,o[++len]=b;
}
sort(o+1,o+len+1);
for (int i=1;i<=(len>>1);i++)
tot1+=o[i];
for (int i=(len>>1)+1;i<=len;i++)
tot2+=o[i];
cout<<useless+tot2-tot1<<endl;
} void Modify(int w,int x,int l,int r,int pos,int tp)
{
sz[w][x]+=tp;
sum[w][x]+=tp*o[pos];
if (l==r) return;
int mid=l+r>>1;
if (pos<=mid) Modify(w,x<<1,l,mid,pos,tp);
else Modify(w,x<<1|1,mid+1,r,pos,tp);
}
int Find(int w,int x,int l,int r,int k)
{
if (l==r) return l;
int mid=l+r>>1;
if (k<=sz[w][x<<1]) return Find(w,x<<1,l,mid,k);
else return Find(w,x<<1|1,mid+1,r,k-sz[w][x<<1]);
}
int Size(int w,int x,int l,int r,int ql,int qr)
{
if (l>=ql&&r<=qr) return sz[w][x];
int mid=l+r>>1,s=0;
if (ql<=mid) s+=Size(w,x<<1,l,mid,ql,qr);
if (qr>mid) s+=Size(w,x<<1|1,mid+1,r,ql,qr);
return s;
}
ll Sum(int w,int x,int l,int r,int ql,int qr)
{
if (l>=ql&&r<=qr) return sum[w][x];
int mid=l+r>>1;ll s=0;
if (ql<=mid) s+=Sum(w,x<<1,l,mid,ql,qr);
if (qr>mid) s+=Sum(w,x<<1|1,mid+1,r,ql,qr);
return s;
}
void work2()
{
for (int i=1;i<=n;i++)
{
cin>>op1>>a>>op2>>b;
if (op1==op2) useless+=abs(a-b);
else useless++,o[++len]=a,o[++len]=b,x[++cnt]=(node){a,b};
}
if (!cnt) {cout<<useless<<endl;exit(0);}
sort(x+1,x+cnt+1);
sort(o+1,o+len+1);
len=unique(o+1,o+len+1)-o-1;
for (int i=1;i<=cnt;i++)
{
x[i].u=lower_bound(o+1,o+len+1,x[i].u)-o;
x[i].v=lower_bound(o+1,o+len+1,x[i].v)-o;
}
for (int i=1;i<=cnt;i++)
Modify(1,1,1,len,x[i].u,1),Modify(1,1,1,len,x[i].v,1);
ans=1e18;
for (int i=1;i<=cnt;i++)
{
Modify(0,1,1,len,x[i].u,1);Modify(0,1,1,len,x[i].v,1);
Modify(1,1,1,len,x[i].u,-1);Modify(1,1,1,len,x[i].v,-1);
int m1=Find(0,1,1,len,i),m2=Find(1,1,1,len,cnt-i);
ll D1=(ll)Size(0,1,1,len,1,m1)*o[m1]-Sum(0,1,1,len,1,m1)+Sum(0,1,1,len,m1,len)-(ll)Size(0,1,1,len,m1,len)*o[m1];
ll D2=(ll)Size(1,1,1,len,1,m2)*o[m2]-Sum(1,1,1,len,1,m2)+Sum(1,1,1,len,m2,len)-(ll)Size(1,1,1,len,m2,len)*o[m2];
ans=min(ans,D1+D2);
}
cout<<useless+ans<<endl;
}
int main()
{
ios::sync_with_stdio(false);
cin>>k>>n;
if (k==1) work1();
else work2();
return 0;
}

[BZOJ4071][APIO2015]八邻旁之桥的更多相关文章

  1. 【BZOJ4071】八邻旁之桥(线段树)

    [BZOJ4071]八邻旁之桥(线段树) 题面 BZOJ权限题,洛谷链接 题解 既然\(k<=2\) 那么,突破口就在这里 分类讨论 ①\(k=1\) 这...不就是中位数吗.... 直接把所有 ...

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

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

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

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

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

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

  5. [APIO2015]八邻旁之桥

    题面在这里 sol 这是一个\(Splay\)的题解 首先,如果一个人的家和办公室在同一侧,我们可以直接预处理; 如果不在同一侧,也可以加上1(当然要过桥啦) 当k==1时 我们设桥的位置为\(pos ...

  6. 题解【luoguP3644 [APIO2015]八邻旁之桥】

    题目链接 题解 家和公司在同侧 简单,直接预处理掉 若 \(k=1\) 取所有的居民的\(\frac{家坐标+公司坐标}{2}\)的所有坐标的正中间建一座桥,使所有居民到的距离最小. 实现方法:线段树 ...

  7. [luoguP3644] [APIO2015]八邻旁之桥(权值线段树)

    传送门 首先如果起点终点都在同一侧可以直接处理,如果需要过桥答案再加1 对于k等于1的情况 桥的坐标为x的话,a和b为起点和终点坐标 $ans=\sum_{1}^{n} abs(a_{i}-x)+ab ...

  8. 洛谷 P3644 [APIO2015]八邻旁之桥(对顶堆维护中位数)

    题面传送门 题意: 一条河将大地分为 \(A,B\) 两个部分.两部分均可视为一根数轴. 有 \(n\) 名工人,第 \(i\) 名的家在 \(x_i\) 区域的 \(a_i\) 位置,公司在 \(y ...

  9. APIO2015 八邻旁之桥/巴邻旁之桥

    题目描述: bz luogu 题解: 贪心+权值线段树. $K=1$的时候,答案为$\sum |x-l| + |x-r|$,所以所有端点排序后取中位数即可. $K=2$的时候,一定是左边的一些走左边的 ...

随机推荐

  1. SynchronousQueue 的联想

    SynchronousQueue介绍 SynchronousQueue是一种阻塞队列,该队列没有任务的容量.内部实现采用了一种性能更好的无锁算法. 代码实现里的Dual Queue,其中每一个put对 ...

  2. [记]Debian alias 设置, 不设置貌似有点不方便习惯

    备忘录,记录下. 不知道 当前有那些 alias 的话 直接输入 alias ,回车就可以看到 alias 列表. 终端输入: vim ~/bash_aliases 然后输入: # some more ...

  3. 10分钟入门kubernetes(上)

    kubernetes简称k8s, 主要用途是automate deployment, scaling, and managment of containerized applications.是目前非 ...

  4. C/C++语言简介之语言组成

    一.数据类型 C的数据类型包括:整型.字符型.实型或浮点型(单精度和双精度).枚举类型.数组类型.结构体类型.共用体类型.指针类型和空类型. 二.常量与变量 常量其值不可改变,符号常量名通常用大写. ...

  5. bzoj1150 [CTSC2007]数据备份Backup 双向链表+堆

    [CTSC2007]数据备份Backup Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2727  Solved: 1099[Submit][Stat ...

  6. 对网站视频资源的管控-禁止通过视频的url访问视频

    一般静态文件的下载是不经过PHP的,直接由web服务器发送到客户端.但有时候需要实现文件下载的权限控制等功能,这时候就需要经由PHP程序来做权限验证.简单粗暴的做法是,在PHP程序里边先验证权限,验证 ...

  7. Java语言的特性

    一.跨平台 借助虚拟机,程序不经修改即可在不同硬件或者软件平台上运行.源代码级(C,C++源码会重新编译),目标代码级(Java). 二.面向对象 以对象为基本单位,使得程序开发变得简单易用,拓展更方 ...

  8. leetcode第一天

    leetcode 第一天 2017年12月24日 第一次刷leetcode真的是好慢啊,三道题用了三个小时,而且都是简单题. 数组 1.(674)Longest Continuous Increasi ...

  9. EmguCV创建/保存图片

    Image图片类 public Image(Bitmap bmp);//采用 Bitmap 图像创建. public Image(string fileName);//指定路径创建图像. public ...

  10. 文件无法复制的原因-IT33

    Win7系统复制数据至其他硬盘或者是移动存储设备是,有时会发生无法复制文件过大的情况.这里先大致介绍一下硬盘文件系统分为NFTS格式和FAT32格式这两种,其中FAT32仅支持单次移动4G以下容量的数 ...