P3644 [APIO2015]八邻旁之桥

题目描述

一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(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\)个居民此时开车从家里到办公室的最短距离。请帮助政府建造桥梁,使得\(D_1 + D_2 + \cdots + D_N\)最小。

输入输出格式

输入格式:

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

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

输出格式:

输出仅为一行,包含一个整数,表示\(D_1 + D_2 + \cdots + D_N\)的最小值。

说明

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

子任务 1 (8 分) \(K = 1\)

\(1 \leq N \leq 1000\)

子任务 2 (14 分) \(K = 1\)

\(1 \leq N \leq 100000\)

子任务 3 (9 分) \(K = 2\)

\(1 \leq N \leq 100\)

子任务 4 (32 分) \(K = 2\)

\(1 \leq N \leq 1000\)

子任务 5 (37 分) \(K = 2\)

\(1 \leq N \leq 100000\)


家和办公室在同一列的可以先处理,过河只会过一次可以先处理

对于剩下的点对\((l,r)\),若桥放在位置\(pos\),则距离总和为

\(\sum_{i=1}^m |l_i-pos|+|r_i-pos|\),\(m\)为有用的点对的个数

我们发现家和办公室对答案的贡献计算方法是没有区别的

则对\(k==1\)时

问题就转换成了,在区间上选择一个点,使区间上的所有点到这个点的距离和最短。

是一个贪心问题,我们取这个区间最中间那个点即可。

对\(k==2\)时

我们思考哪个桥管哪些点

如果一个桥在点对\((l,r)\)中间,那么走哪个都是无所谓的

若果不在,则答案为\(|pos \times 2-l-r|=|pos \times 2-(l+r)|\),\((l+r)\)离哪个\(pos\)近,就会走哪个桥。

于是我们可以以\((l+r)\)为关键字进行排序,枚举端点进行统计。

如何快速统计呢?我们需要支持一个删减元素,查询区间和查询中位数的数据结构

平衡树和主席树都不错

事实上主席树常数会优秀很多

这里写的的fhq_treap


Code:

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <cstring>
#define ll long long
#define ls ch[now][0]
#define rs ch[now][1]
using namespace std;
const int N=200010;
int ch[N][2],val[N],tot;
ll dat[N],siz[N],sum[N];
struct node
{
ll s,t,k;
bool friend operator <(node n1,node n2)
{
return n1.k<n2.k;
}
node(ll s,ll t,ll k)
{
this->s=s;
this->t=t;
this->k=k;
}
node(){}
}e[N];
void updata(int now)
{
siz[now]=siz[ls]+siz[rs]+1;
sum[now]=sum[ls]+sum[rs]+dat[now];
}
int k0,n,m,root;
ll ans;
void split(int now,ll k,int &x,int &y)
{
if(!now) {x=y=0;return;}
if(dat[now]<=k)
x=now,split(rs,k,rs,y);
else
y=now,split(ls,k,x,ls);
updata(now);
}
int Merge(int x,int y)
{
if(!x||!y) return x+y;
if(val[x]<val[y])
{
ch[x][1]=Merge(ch[x][1],y);
updata(x);
return x;
}
else
{
ch[y][0]=Merge(x,ch[y][0]);
updata(y);
return y;
}
}
int new_node(ll k)
{
dat[++tot]=k;val[tot]=rand();siz[tot]=1;sum[tot]=k;
return tot;
}
void Insert(ll k)
{
int x,y;
split(root,k,x,y);
root=Merge(x,Merge(new_node(k),y));
}
void extrack(ll k)
{
int x,y,z;
split(root,k,x,y);
split(x,k-1,x,z);
z=Merge(ch[z][0],ch[z][1]);
root=Merge(x,Merge(z,y));
}
ll Rank(int now,int x)//查询排名为x的点
{
if(!now) return 0;
if(x<=siz[ls]) return Rank(ls,x);
else if(x>siz[ls]+1) return Rank(rs,x-siz[ls]-1);
else return dat[now];
}
ll query(ll k)//返回小于等于k的点的权值之和
{
int x,y,Siz=siz[root]>>1;
ll s=0;
split(root,k-1,x,y);
s=sum[x]<<1;
s+=k*(Siz-siz[x])<<1;
root=Merge(x,y);
return s;
}
ll cal()
{
ll k=Rank(root,siz[root]>>1);
return sum[root]-query(k);
}
ll Ans[N];
void work2()
{
root=tot=0;
memset(ch,0,sizeof(ch));
ll sum0=Ans[m];
for(register int i=m;i;i--)
{
Insert(e[i].s);
Insert(e[i].t);
sum0=min(sum0,cal()+Ans[i-1]);
}
printf("%lld\n",sum0+ans);
}
int main()
{
srand(time(0));
scanf("%d%d",&k0,&n);
ll s,t;char p,q;
for(register int i=1;i<=n;i++)
{
scanf("\n");
scanf("%c%lld %c%lld",&p,&s,&q,&t);
if(p==q)
ans+=abs(t-s);
else
{
ans++;
node tt(s,t,s+t);
e[++m]=tt;
}
}
sort(e+1,e+1+m);
for(int i=1;i<=m;i++)
{
Insert(e[i].s);
Insert(e[i].t);
Ans[i]=cal();
}
if(k0==1) printf("%lld\n",Ans[m]+ans);
else work2();
return 0;
}

2018.7.29

洛谷 P3644 [APIO2015]八邻旁之桥 解题报告的更多相关文章

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

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

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

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

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

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

  4. [APIO2015]八邻旁之桥

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 01-JVM内存模型:程序计数器

    一.JVM模型概述 java虚拟机(JVM)在java程序运行的过程中,会将它所管理的内存划分为若干个不同的数据区域,这些区域有的随着JVM的启动而创建,有的随着用户线程的启动和结束而建立和销毁.一个 ...

  2. VIN码识别(车架号识别)在二手车交易中的应用

    最新数据统计,2015年,中国卖出2110万辆新车,相比之下,美国卖出去了1740辆新车.然而,如果算上二手车,美国的汽车市场销量将扩展到4000多辆,而中国的乘用车才不到3000万辆. 销售总额上, ...

  3. lintcode First Unique Number In Stream

    First Unique Number In Stream 描述: Given a continuous stream of numbers, write a function that return ...

  4. POJ 3046

    题目大意:蚂蚁牙黑,蚂蚁牙红:有A只蚂蚁,来自T个家族,分别记为ant[i]个.同一个家族的蚂蚁长得一样,但是不同家族的蚂蚁牙齿颜色不同.任取n只蚂蚁(S <= n <= B),求能组成几 ...

  5. 如何使用AEditor制作一个简单的H5交互页demo

    转载自:http://www.alloyteam.com/2015/06/h5-jiao-hu-ye-bian-ji-qi-aeditor-jie-shao/ 本教程演示如何使用AEditor制作一个 ...

  6. NHibernate3快速上手教程FluentNHibernate配置与DBHelper(已过期,有更好的)

    很多学习NHibernate的新手很容易卡在配置文件这一关,正所谓万事开头难,上手后再配合官方文档就比较容易了. 网上关于配置文件的资料非常多,但由于版本的问题,许多老的教程中都没有明确指出类库的版本 ...

  7. [Clr via C#读书笔记]Cp2生成打包部署和管理应用程序和类型

    Cp2生成打包部署和管理应用程序和类型 部署问题 DLL Hell;安装的复杂性:安全性:代码访问安全性. csc.exe的简单使用. 元数据 定义表:引用表:清单表: 程序集 重用,版本控制,安全的 ...

  8. ARM架构中的程序执行与调用

    ARM架构中的程序执行与调用 1. 几个名词 ABI : 可执行文件必须遵守的规范,以在特定执行环境中运行: 单独产生的可重定址的文件必须遵守的规范,以用来链接和执行. EABI: 适用于嵌入式环境的 ...

  9. 京东2018秋招c++岗 神奇数

    题意大概是: 一个数比如242,把所有数字分成两组,而且两组的和相等,那么这个数就是神奇数,此时242,能够分成{2,2}和{4},所以242是神奇数. 题目要求输入n和m求[n,m]区间内神奇数的个 ...

  10. 蓝牙核心技术概述(四):蓝牙协议规范(HCI、L2CAP、SDP、RFOCMM)(转载)

    一.主机控制接口协议  HCI 蓝牙主机-主机控模型 蓝牙软件协议栈堆的数据传输过程: 1.蓝牙控制器接口数据分组:指令分组.事件分组.数据分组(1).指令分组 如:Accpet Connection ...