【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$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...
随机推荐
- EFCore笔记之查询数据
查询数据 基础查询,Linq100实例: https://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b using (var context = ...
- BZOJ 1576 [USACO]安全路经Travel (树剖+线段树)
题目大意: 给你一张无向图,求1到其他节点 不经过最短路的最后一条边 的最短路长度,保证每个节点的最短路走法唯一 神题,$USACO$题目的思维是真的好 先$dijkstra$出最短路树 对于每个节点 ...
- BZOJ 4990 [USACO17FEB] Why Did the Cow Cross the Road II P (树状数组优化DP)
题目大意:给你两个序列,你可以两个序列的点之间连边 要求:1.只能在点权差值不大于4的点之间连边 2.边和边不能相交 3.每个点只能连一次 设表示第一个序列进行到 i,第二个序列进行到 j,最多连的边 ...
- df与du查看磁盘空间使用不一致的解决方法
近一段时间,某台服务器的磁盘空间使用不太正常,与其他的服务器相比,严重超出磁盘空间使用 使用df与du相关命令查看,具体结果如下: du -hFilesystem Size Used A ...
- (转载)使用Maven构建多模块项目
原文:https://www.cnblogs.com/xdp-gacl/p/4242221.html#undefined 在平时的Javaweb项目开发中为了便于后期的维护,我们一般会进行分层开发,最 ...
- Windows系统环境变量、JAVA环境变量配置以及JVM加载过程
一:用户变量和系统变量的区别 右击我的电脑.属性.高级系统设置.环境变量. 对话框的上面为Administrator的用户变量,对话框的下面为系统变量.我们所说的环境变量一般指系统环境变量,对所有用户 ...
- 洛谷 P3047 [USACO12FEB]附近的牛Nearby Cows
P3047 [USACO12FEB]附近的牛Nearby Cows 题目描述 Farmer John has noticed that his cows often move between near ...
- BestCoder Round #52 (div.2) HDU 5418 Victor and World (DP+状态压缩)
[题目链接]:pid=5418">click here~~ [题目大意]: 问题描写叙述 经过多年的努力,Victor最终考到了飞行驾照. 为了庆祝这件事,他决定给自己买一架飞机然后环 ...
- [Python + Unit Testing] Write Your First Python Unit Test with pytest
In this lesson you will create a new project with a virtual environment and write your first unit te ...
- 【SPOJ-GSHOP】Rama and Friends【贪心】【细节】
题意: 给出n个非严格递增的整数(可能有负数),必须操作k次.每次能够把当中一个数变为它的相反数,使得终于的数列和最大. 输出这个最大和. 考验怎样出坑数据卡自己的程序... #include < ...