【BZOJ4071】【APIO2015】巴邻旁之桥
题意:
Description
一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B。
子任务 1 (8 分)K=1,1≤N≤1000
子任务 2 (14 分)K=1,1≤N≤100000
子任务 3 (9 分)K=2,1≤N≤100
子任务 4 (32 分)K=2,1≤N≤1000
子任务 5 (37 分)K=2,1≤N≤100000
Input
输入的第一行包含两个正整数 K 和 N,分别表示桥的上限数量和居民的数量。
Output
题解:
首先,这题可以三分!可以三分!可以三分!
认(sui)真(bian)分(cai)析(xiang)一下可以发现,$K=1$时总花费时间随桥从左到右变化的函数是个单峰函数,$K=2$时是两个单峰函数通过某种变换之后叠加在一起,最后还是个单峰函数(然而我并不会证)
因此可以先三分第一个桥,再三分第二个桥,三分套三分的时间复杂度是$O(nlog^210^9)$的,手算大概有2.5亿,实测可以过掉前四个subtask,获得63分的好成绩(雾)
正解是权值线段树动态维护中位数。。。
$K=1$就不说了,大家都会。。。
$K=2$时有一个结论:每个人必定会走更接近$\frac{A_i+B_i}{2}$的那座桥,易得这样必定更优;
所以可以先按照$A_i+B_i$排序,左半边的人就会走左桥,右半边就走右桥;
然后就没了。。。左右各写一个数据结构,支持快速插入/删除,快速查询中位数和区间和,可以直接splay,也可以用权值线段树黑科技来做(新技能get√)
ps:所谓的黑科技就是,左右儿子哪个size大就走哪个,最后的叶节点就是中位数。。。
代码:
三分:(请木公爷来卡常啊啊啊)
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 10000000000000000
#define eps 1e-9
using namespace std;
typedef long long ll;
struct pp{
ll s1,s2,t1,t2;
}p[];
ll n,K,ans=inf,l,r,maxn=;
char sd1[],sd2[];
ll gaogao(ll k,ll kk){
ll ret=;
for(ll i=;i<=n;i++){
if(p[i].s1==p[i].s2)ret+=abs(p[i].t1-p[i].t2);
else ret+=min(abs(p[i].t1-k)+abs(p[i].t2-k)+,abs(p[i].t1-kk)+abs(p[i].t2-kk)+);
}
return ret;
}
ll gao(ll k){
if(K==){
ll ret=;
for(ll i=;i<=n;i++){
if(p[i].s1==p[i].s2)ret+=abs(p[i].t1-p[i].t2);
else ret+=abs(p[i].t1-k)+abs(p[i].t2-k)+;
}
return ret;
}
ll ret=inf,l=,r=maxn;
while(l+<=r){
ll mid=l+(r-l)/,mmid=r-(r-l)/;
if(gaogao(k,mid)<=gaogao(k,mmid))r=mmid;
else l=mid;
}
for(ll i=l;i<=r;i++){
ret=min(ret,gaogao(k,i));
}
return ret;
}
int main(){
scanf("%lld%lld",&K,&n);
for(ll i=;i<=n;i++){
scanf("%s%lld%s%lld",sd1,&p[i].t1,sd2,&p[i].t2);
p[i].s1=sd1[]-'A';
p[i].s2=sd2[]-'A';
maxn=max(maxn,max(p[i].t1,p[i].t2));
}
l=,r=maxn;
while(l+<=r){
ll mid=l+(r-l)/,mmid=r-(r-l)/;
if(gao(mid)<=gao(mmid))r=mmid;
else l=mid;
}
for(ll i=l;i<=r;i++){
ans=min(ans,gao(i));
}
printf("%lld",ans);
return ;
}
权值线段树:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define inf 1000000000000000
#define eps 1e-9
using namespace std;
typedef long long ll;
struct pp{
ll t1,t2;
friend bool operator <(pp a,pp b){
return a.t1+a.t2<b.t1+b.t2;
}
}p[];
struct node{
ll v,siz;
}t[][];
ll n,k,t1,t2,x1,x2,x3,x4,m1,m2,nw1=,nw2=,els=,sum=,cnt=,ans=inf,num[];
char s1[],s2[];
void updata(ll l,ll r,ll u,ll p,ll x,ll ch){
t[u][ch].siz+=x;
t[u][ch].v+=x*num[p];
if(l==r)return;
ll mid=(l+r)/;
if(p<=mid)updata(l,mid,u*,p,x,ch);
else updata(mid+,r,u*+,p,x,ch);
}
ll get(ll l,ll r,ll u,ll x,ll ch){
if(l==r)return l;
ll mid=(l+r)/;
if(x<=t[u*][ch].siz)return get(l,mid,u*,x,ch);
else return get(mid+,r,u*+,x-t[u*][ch].siz,ch);
}
ll query(ll l,ll r,ll u,ll L,ll R,ll ch,ll xx){
if(L<=l&&r<=R){
return xx?t[u][ch].v:t[u][ch].siz;
}
ll mid=(l+r)/,ret=;
if(L<=mid)ret+=query(l,mid,u*,L,R,ch,xx);
if(mid<R)ret+=query(mid+,r,u*+,L,R,ch,xx);
return ret;
}
int main(){
scanf("%lld%lld",&k,&n);
if(k==){
for(ll i=;i<=n;i++){
scanf("%s%lld%s%lld",s1,&t1,s2,&t2);
if(s1[]==s2[])els+=abs(t1-t2);
else{
num[++cnt]=t1;
num[++cnt]=t2;
}
}
ans=els+cnt/;
sort(num+,num+cnt+);
for(ll i=;i<=cnt;i++){
ans+=abs(num[i]-num[cnt/]);
}
printf("%lld",ans);
}else{
for(ll i=;i<=n;i++){
scanf("%s%lld%s%lld",s1,&t1,s2,&t2);
if(s1[]==s2[])els+=abs(t1-t2);
else{
num[++cnt]=t1;
num[++cnt]=t2;
p[++sum].t1=t1;
p[sum].t2=t2;
}
}
if(!sum)return printf("%lld\n",els),;
els+=sum;
sort(num+,num+cnt+);
cnt=unique(num+,num+cnt+)-num-;
sort(p+,p+sum+);
for(ll i=;i<=sum;i++){
nw1+=p[i].t1+p[i].t2;
p[i].t1=lower_bound(num+,num+cnt+,p[i].t1)-num;
p[i].t2=lower_bound(num+,num+cnt+,p[i].t2)-num;
updata(,cnt,,p[i].t1,,);
updata(,cnt,,p[i].t2,,);
}
for(ll i=;i<=sum;i++){
nw2+=num[p[i].t1]+num[p[i].t2];
nw1-=num[p[i].t1]+num[p[i].t2];
updata(,cnt,,p[i].t1,,);
updata(,cnt,,p[i].t1,-,);
updata(,cnt,,p[i].t2,,);
updata(,cnt,,p[i].t2,-,);
m1=get(,cnt,,i,);
m2=get(,cnt,,sum-i,);
x1=query(,cnt,,,m1,,);
x2=query(,cnt,,,m2,,);
x3=query(,cnt,,,m1,,);
x4=query(,cnt,,,m2,,);
ans=min(ans,x3*num[m1]-x1+(nw2-x1)-(i*-x3)*num[m1]+x4*num[m2]-x2+(nw1-x2)-((sum-i)*-x4)*num[m2]);
}
printf("%lld",ans+els);
}
return ;
}
【BZOJ4071】【APIO2015】巴邻旁之桥的更多相关文章
- [bzoj4071] [Apio2015]巴邻旁之桥
Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...
- 【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$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...
随机推荐
- GridBagLayout使用案例+获取目录下所有的文件+获取创建时间及最后修改时间
package vvv; import java.awt.Dimension;import java.awt.GridBagConstraints;import java.awt.GridBagLay ...
- zabbix部署监控端(server)以及页面优化
实验环境准备 172.20.10.2 server.zabbix.com 172.20.10.3 agent.zabbix.com 172.20.10.8 windows10 Server 端 [ro ...
- Git的初始化设置
Git安装成功之后,新建一个初始化的仓库以及配置GitHub仓库 Git配置GitHub账户 安装完成之后要进行git的配置,这里配置的是GitHub账户 MisSa@DESKTOP-PIQ06QO ...
- JS 将有父子关系的数组转换成树形结构数据
将类似如下数据转换成树形的数据 [{ id: 1, name: '1', }, { id: 2, name: '1-1', parentId: 1 }, { id: 3, name: '1-1-1', ...
- POJ 2661Factstone Benchmark(斯特林公式)
链接:传送门 题意:一个人自命不凡,他从1960年开始每10年更新一次计算机的最长储存长数.1960年为4位,每10年翻一倍.给出一个年份y,问这一年计算机可以执行的n!而不溢出的最大n值 思路:如果 ...
- Codeforces 679A Bear and Prime 100
链接:传送门 题意:给你一个隐藏数,这个隐藏数在[2,100]之间,现在最多可以询问20次,每次询问的是这个数是不是隐藏数的底数,是为yes,不是为no,每次询问后都需要flush一下输出缓冲区,最后 ...
- BZOJ 4182 Shopping (点分治+树上多重背包)
题目大意:给你一颗树,你有$m$元钱,每个节点都有一种物品,价值为$w$,代价为$c$,有$d$个,如果在$u$和$v$两个城市都购买了至少一个物品,那么$u,v$路径上每个节点也都必须买至少一个物品 ...
- [AngularJS]Chapter 3 使用AngularJS构建应用程序
本章内容提要: 如何布置AngularJS进行快速开发 开启服务器进行测试 使用Karma进行单元测试用例测试 编译压缩AngularJS进行生产 使用Batarang进行Debug 如何简化开发工作 ...
- ZOJ 2705
这题,找找规律,可以发现一个斐波那契数列.按照斐波那契数列求和,知道, SUM=Fn+2-F1,于是,该长度为Fn+2的倍数.因为斐波那契数列不一定是从1开始的,而从2开始的每个数都是从1开始的倍数. ...
- 关闭 sftp
vi /etc/ssh/sshd_config 注释掉这行Subsystem sftp /usr/libexec/openssh/sftp-server /etc/rc.d/init.d/ss ...