Link:

BZOJ 4071传送门

Solution:

首先算出能提前算的贡献

$K=1$:肯定选中间的点,小学数学

$K=2$:对于每对$(x,y)$一定选离$(x+y)/2$近的桥

也就是说将$(x,y)$按$(x+y)/2$的值排序后一定恰有一个分割点使得两边选择不同的桥!

考虑如何如何快速枚举所有分割点时的答案:

需要支持插入、删除、求中位数及两边的和,明显选择$Splay$来维护(求和更容易些)

这样先将所有数对加进一个$Splay$,再不断将其中的数移向另一棵$Splay$即可

注意:可能以前的$Splay$板子容易出不少锅啊……

首先$Update$时最好对$z$进行判断,然后$Splay$最后也要$Pushup$否则会在树高低时不更新$size$

Code:

#include <bits/stdc++.h>

using namespace std;
#define X first
#define Y second
typedef double db;
typedef long long ll;
typedef pair<int,int> P;
const int MAXN=2e5+;//注意范围
const ll INF=<<; struct Splay
{
ll sum[MAXN];
int rt,tot,f[MAXN],sz[MAXN],cnt[MAXN],ch[MAXN][],val[MAXN];
void update(int x)
{
sz[x]=sz[ch[x][]]+sz[ch[x][]]+cnt[x];
sum[x]=sum[ch[x][]]+sum[ch[x][]]+1ll*val[x]*cnt[x];
}
void rotate(int x)
{
int y=f[x],z=f[y],k=(ch[y][]==x);
//最好对z特判一下防止对ch[0]操作
if(z) ch[z][ch[z][]==y]=x;f[x]=z;
ch[y][k]=ch[x][k^];f[ch[x][k^]]=y;
ch[x][k^]=y;f[y]=x;
update(y);update(x);
}
void splay(int x,int up)
{
while(f[x]!=up)
{
int y=f[x],z=f[y];
if(z!=up) (ch[y][]==x)^(ch[z][]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!up) rt=x;
//!!!!!!!!
update(x);//可能f[x]=up,但也要update
}
void insert(int x)
{
int k=rt,anc=;
while(k&&val[k]!=x)
anc=k,k=ch[k][x>val[k]];
if(k) cnt[k]++;
else
{
k=++tot;
if(anc) ch[anc][x>val[anc]]=k;
val[k]=x;cnt[k]=;f[k]=anc;sz[k]=;
}
splay(k,);
}
void find(int x)
{
int k=rt;
while(x!=val[k]&&ch[k][x>val[k]])
k=ch[k][x>val[k]];
splay(k,);
}
int kth(int x)
{
int k=rt;
//对当前为空的情况特判
if(sz[k]<x||!x) return ;
while(true)
{
if(x>sz[ch[k][]]+cnt[k])
x-=sz[ch[k][]]+cnt[k],k=ch[k][];
else if(x<=sz[ch[k][]]) k=ch[k][];
else return k;
}
}
//不用加边界的删除法
void del(int x)
{
find(x);
if(val[rt]!=x) return;
if(cnt[rt]>) cnt[rt]--;
else if(!ch[rt][]||!ch[rt][])
{
int k=ch[rt][]+ch[rt][];
f[k]=;rt=k;
}
else
{
int k=ch[rt][];
while(ch[k][]) k=ch[k][];
splay(k,rt);
ch[k][]=ch[rt][];
f[ch[k][]]=k;
rt=k;f[k]=;
}
//由于后面没有splay了要update
update(rt);
}
ll query()
{
int k=kth(sz[rt]/);
if(!k) return ;splay(k,);
ll ret1=1ll*val[k]*sz[ch[k][]]-sum[ch[k][]];
ll ret2=sum[ch[k][]]-1ll*val[k]*sz[ch[k][]];
return ret1+ret2;
}
}s1,s2; char a[],b[];
ll res=1ll<<,pre;
int n,x,y,k,tot;P dat[MAXN]; bool cmp(P a,P b){return a.X+a.Y<b.X+b.Y;}; int main()
{
scanf("%d%d",&k,&n);
for(int i=;i<=n;i++)
{
scanf("%s%d%s%d",a,&x,b,&y);
if(a[]==b[]) pre+=abs(x-y);
else dat[++tot]=P(x,y),pre++;
}
//注意特判!!!
if(!tot) return printf("%lld",pre),;
sort(dat+,dat+tot+,cmp); for(int i=;i<=tot;i++)
s1.insert(dat[i].X),s1.insert(dat[i].Y);
if(k==) return printf("%lld",s1.query()+pre),; for(int i=;i<=tot;i++)
{
s1.del(dat[i].X);s1.del(dat[i].Y);
s2.insert(dat[i].X);s2.insert(dat[i].Y);
res=min(res,s1.query()+s2.query());
}
printf("%lld",res+pre);
return ;
}

[BZOJ 4071] 巴邻旁之桥的更多相关文章

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

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

  2. 4071: [Apio2015]巴邻旁之桥

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

  3. BZOJ4071 & 洛谷3644 & UOJ112:[APIO2015]巴邻旁之桥——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4071 https://www.luogu.org/problemnew/show/P3644 ht ...

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

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

  5. 【BZOJ4071】【APIO2015】巴邻旁之桥

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

  6. bzoj 4071: [Apio2015]巴邻旁之桥【splay】

    用权值线段树会容易一些并快一些,但是想复健一下splay所以打了splay 然后果然不会打了. 解题思路: 首先把家和办公室在同一侧的提出来直接加进答案里: 对于k=1,直接选所有办公室和家的中位数即 ...

  7. [APIO2015]巴邻旁之桥

    Bzoj权限题 luogu题面 先去掉同边的 首先k==1,即求一个点j 使\(\sum_{i\in A} |D_i - D_j| + \sum_{i\in B} |D_i - D_j|\)最小 因为 ...

  8. 【LOJ】#2888. 「APIO2015」巴邻旁之桥 Palembang Bridges

    题解 发现我们选择一座桥会选择力\(\frac{s + t}{2}\)较近的一座桥 然后我们只需要按照\(s + t\)排序,然后枚举断点,左边取所有s和t的中位数,右边同理 动态求中位数用平衡树维护 ...

  9. 「APIO2015」巴邻旁之桥 Palembang Bridges

    贪心 先转化一下题意 首先如果一个人的家和办公室在河同一侧那么建桥的时候不用去考虑它,最终把答案加上即可 在河两侧的家和办公室互换不影响答案,那么可以把这个抽象到一个区间$[l,r]$,距离就是$|l ...

随机推荐

  1. oschina ios开发学习

    应该跟android版的类似,例如服务器端在oschina-prefix.pch里 #define api_news_list @"http://www.oschina.net/action ...

  2. 常用的css3新特性总结

    1:CSS3阴影 box-shadow的使用和技巧总结: 基本语法是{box-shadow:[inset] x-offset y-offset blur-radius spread-radiuscol ...

  3. windows7下安装配置phonegap3.0 (cordavo)开发环境 (涉及android sdk配置)

    之前在mac上安装调试过phonegap,现在公司用的是windows7,所以不得不再进行一次windows下的配置工作,顺便也写下来了 主要麻烦的地方是要在win7下添加好几个环境变量,这一块地方特 ...

  4. 47、求1+2+3+...+n

    一.题目 求1+2+3+...+n,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B:C). 二.解法 public class Solut ...

  5. 【swupdate文档 五】从可信的来源更新镜像

    从可信的来源更新镜像 现在越来越重要的是,设备不仅要能安全地进行更新操作, 而且要能够验证发送的图像是否来自一个已知的源, 并且没有嵌入恶意软件. 为了实现这个目标,SWUpdate必须验证传入的镜像 ...

  6. SQLite3数据库的操作

    数据库的操作 我们在这个项目中使用的是SQLITE3数据库软件. 通过使用SQLITE3进行创建数据库,创建表,插入记录,查询记录,更新记录,关闭数据库等操作来实现将相应的数据存入数据库中. 打开数据 ...

  7. screen命令使用方法【转】

    在linux的环境中,我们想要在后台持续运行一些脚本,但是又因为关闭这个tty的话,脚本就会中断,这个时候我们就需要screen这个工具的帮助啦! 基础   1 首先先查看下否则有这个工具.如果运行s ...

  8. linux/centos定时任务cron

    https://www.cnblogs.com/p0st/p/9482167.html cron: crond进程 crontab修改命令 * * * * *  command parameter & ...

  9. Morris Traversal方法遍历

    实现二叉树的遍历且只需要O(1)的空间. 参考:http://www.cnblogs.com/AnnieKim/archive/2013/06/15/MorrisTraversal.html

  10. [MySQL] specified key was too long max key length is 767bytes

    https://blog.csdn.net/u012099869/article/details/53815084/