【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$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...
随机推荐
- Apache2.2伪静态配置
最近由于工作的需要要配置一下Apache的伪静态化,在网上搜了好多都无法完成,所以觉得有必要在这里写一下. 第一步:打开Apache的httpd.conf文件,把LoadModule rewrite_ ...
- oracle错误ORA-00604 递归sql级别1出现错误 ora-00942 表或试图不存在 ORA-06512 在line 11
错误截图如下: 搜索了很多方法,但是都没有办法解决,不过最终还是找到了一个好的解决办法, 多谢那位仁兄的博客[http://blog.itpub.net/519536/viewspace-689469 ...
- 「JavaSE 重新出发」05.03.01 利用反射分析类
在 java.lang.reflect 包中有三个类 Field, Method 和 Constructor 分别用于描述类的域.方法和构造器. Class 类中的 getFields, getMet ...
- ___Manacher(线性回文子串处理算法)
昨晚的bc做得好忧郁----- 第一题改了好久好久好久----等改完发现比赛已经结束了(发现是枚举子集的位运算那儿写错了--) 第二题是判断能否将一个字符串划分成三段回文串 今天学了一点点 Mana ...
- 转载:常用 Git 命令清单
转载:常用 Git 命令清单 原文地址:http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html 作者: 阮一峰 我每天使用 Git , ...
- 关于使用css伪类实现小图标
效果: .person_use>span{ display:block; width:0; height:0; border-width:10px; border-style:solid; bo ...
- 机器学习实战笔记--AdaBoost(实例代码)
#coding=utf-8 from numpy import * def loadSimpleData(): dataMat = matrix([[1. , 2.1], [2. , 1.1], [1 ...
- BZOJ 1030 [JSOI2007]文本生成器 (Trie图+DP)
题目大意:给你一堆字符串,一个串不合法的条件是这些字符串中任意一个是这个串的子串,求合法的串的数量 其实这道题比 [HNOI2008]GT考试 那道题好写一些,但道理是一样的 只不过这道题的答案可以转 ...
- markdown图片设置
工具:typora 1. 设置图片大小(本节引用自 https://support.typora.io/Resize-Image/) Typora允许使用<img>标签显示图像,也可用于调 ...
- Virtual Box 新建一个虚拟机安装系统(补充:WIN7 64 bit 系统虚拟机无法安装 64 bit 系统问题)
1.安装Virtual Box好后,点击新建 2.配置内存大小,这个根据自己需要配置就好 3.创建虚拟硬盘 这里选择固定分配.动态分配都可以,接下来就分配硬盘大小了 4.新建好后我们点击刚才建立的虚拟 ...