bzoj 4071: [Apio2015]巴邻旁之桥【splay】
用权值线段树会容易一些并快一些,但是想复健一下splay所以打了splay
然后果然不会打了。
解题思路:
首先把家和办公室在同一侧的提出来直接加进答案里;
对于k=1,直接选所有办公室和家的中位数即可,因为显然如果选的点两边的办公室和家的点不一样多的话,显然可以向多的一侧移动来使得总路程减少;
对于k=2,所有人按家和办公室的中点排序,然后显然有一个断点,左边的人走左边的桥,右边的人走右边的桥。因为选择距离中点近的桥一定不会变差。然后枚举这个断点,先从左到右依次加进去,每次加完之后把当前在splay里的这部分答案(中位数和其他数的差得绝对值)存起来,然后从左到右依次删掉,此时splay里的是除了1~i的部分,把这部分的答案加上之前存起来的答案就是最后答案,然后在这些答案里取min即可。
!这里因为取min所以初始值设为inf了,注意特判一下没有家和办公室在两岸的人把初始值改成0
splay注意事项:如果涉及插入,要先插两个辅助点inf,-inf进去,涉及删除则要插四个;
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
const int N=200005;
const long long inf=1e15;
int k,n,top,root,tot;
long long q[N],ans;
struct qwe
{
int s,t,m;
qwe(int S=0,int T=0,int M=0)
{
s=S,t=T,m=M;
}
}a[N];
struct Splay
{
int f,c[2],s;
long long sum,v;
}t[N];
inline bool cmp(const qwe &a,const qwe &b)
{
return a.m<b.m;
}
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
inline void ud(int x)
{
t[x].s=t[t[x].c[0]].s+t[t[x].c[1]].s+1;
t[x].sum=t[t[x].c[0]].sum+t[t[x].c[1]].sum+(long long)t[x].v;
}
void zhuan(int x,int &k)
{
int y=t[x].f,z=t[y].f,l=t[y].c[0]!=x,r=l^1;
if(y!=k)
t[z].c[t[z].c[0]!=y]=x;
else
k=x;
t[x].f=z;
t[y].c[l]=t[x].c[r];
t[t[y].c[l]].f=y;
t[x].c[r]=y;
t[y].f=x;
ud(y);
ud(x);
}
void splay(int x,int &k)
{
while(x!=k)
{
int y=t[x].f,z=t[y].f;
if(y!=k)
{
if((t[y].c[0]==x)^(t[z].c[0]==y))
zhuan(x,k);
else
zhuan(y,k);
}
zhuan(x,k);
}
}
int paiming(int x,int va)
{
int r=0;
while(x)
{
if(t[x].v>va)
x=t[x].c[0];
else
r+=t[t[x].c[0]].s+1,x=t[x].c[1];
}
return r;
}
int shu(int x,int k)
{
if(!x)
return 0;
if(t[t[x].c[0]].s+1==k)
return x;
else if(t[t[x].c[0]].s>=k)
return shu(t[x].c[0],k);
else
return shu(t[x].c[1],k-t[t[x].c[0]].s-1);
}
void charu(int k)
{
int x=shu(root,paiming(root,k));
splay(x,root);
int y=shu(t[x].c[1],1);
splay(y,t[x].c[1]);
t[y].c[0]=++tot;
t[tot].f=y;
t[tot].v=k;
t[tot].sum=k;
t[tot].s=1;
ud(y);
ud(x);
}
void shanchu(int k)
{
int x=shu(root,paiming(root,k)-1);//cerr<<k<<" "<<paiming(root,k)<<endl;
splay(x,root);
int y=shu(t[x].c[1],2);
splay(y,t[x].c[1]);
t[t[y].c[0]].f=0;
t[y].c[0]=0;
ud(y);
ud(x);
}
long long ques(int x)
{//cerr<<t[x].v<<" ";
splay(x,root);
return 1ll*t[x].v*(t[t[x].c[0]].s-2)-t[t[x].c[0]].sum+t[t[x].c[1]].sum-1ll*t[x].v*(t[t[x].c[1]].s-2)-4*inf;
}
int main()
{
k=read(),n=read();
for(int i=1;i<=n;i++)
{
char c1=0,c2=0;
while(c1!='A'&&c1!='B')
c1=getchar();
int x=read();
while(c2!='A'&&c2!='B')
c2=getchar();
int y=read();//cerr<<c1<<" "<<c2<<" "<<x<<" "<<y<<endl;
if(c1==c2)
ans+=abs(y-x);
else
a[++top]=qwe(x,y,abs(x+y)>>1);
}
n=top;
if(k==1)
{
int e[N];
for(int i=1;i<=n;i++)
e[i]=a[i].s,e[i+n]=a[i].t;
sort(e+1,e+1+n*2);
int p=e[n];
for(int i=1;i<=n*2;i++)
ans+=1ll*abs(e[i]-p);
printf("%lld\n",ans+n);
return 0;
}
sort(a+1,a+1+n,cmp);
tot=4;
t[1].v=-inf,t[1].s=4,t[1].c[0]=2,t[1].c[1]=3,root=1;
t[2].v=-inf,t[2].sum=-inf,t[2].s=1,t[2].f=1;
t[3].v=inf,t[3].sum=2ll*inf,t[3].s=2,t[3].f=1,t[3].c[1]=4;
t[4].v=inf,t[4].sum=inf,t[4].s=1,t[4].f=3;
for(int i=1;i<=n;i++)
{
charu(a[i].s),charu(a[i].t);
q[i]=ques(shu(root,i+2));//cerr<<q[i]<<endl;
}//cerr<<"ok"<<endl;
long long sum=inf;
if(!n)
sum=0;
for(int i=1;i<=n;i++)
{
shanchu(a[i].s),shanchu(a[i].t);
sum=min(sum,q[i]+ques(shu(root,n-i+2)));
}
printf("%lld\n",ans+sum+n);
return 0;
}
bzoj 4071: [Apio2015]巴邻旁之桥【splay】的更多相关文章
- 4071: [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 ...
- [bzoj4071] [Apio2015]巴邻旁之桥
Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 10000 ...
- [APIO2015]巴邻旁之桥
Bzoj权限题 luogu题面 先去掉同边的 首先k==1,即求一个点j 使\(\sum_{i\in A} |D_i - D_j| + \sum_{i\in B} |D_i - D_j|\)最小 因为 ...
- 洛谷 P3644 [APIO2015]八邻旁之桥 解题报告
P3644 [APIO2015]八邻旁之桥 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好\(1000000001\)栋的建筑 ...
- [APIO2015]八邻旁之桥——非旋转treap
题目链接: [APIO2015]八邻旁之桥 对于$k=1$的情况: 对于起点和终点在同侧的直接计入答案:对于不在同侧的,可以发现答案就是所有点坐标与桥坐标的差之和+起点与终点不在同一侧的人数. 将所有 ...
- 【BZOJ4071】【APIO2015】巴邻旁之桥
题意: Description 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域 A 和区域 B. 每一块区域沿着河岸都建了恰好 1000000001 栋的建筑,每条岸边的建筑都从 0 编号到 1 ...
- [BZOJ4071][APIO2015]八邻旁之桥
BZOJ(这题是BZOJ权限题,有权限号的就去看看吧) Luogu(良心洛谷) 题目描述 一条东西走向的穆西河将巴邻旁市一分为二,分割成了区域\(A\)和区域\(B\). 每一块区域沿着河岸都建了恰好 ...
随机推荐
- Eclipse Explorer插件快速打开项目文件在系统资源管理器
官网:https://github.com/Jamling/eclipse-explorer 安装: 1.在线安装 [Help]->[Eclipse Marketplace]搜索:Eclipse ...
- 【网络】TCP协议
一.概述 主要特点: 1)面向连接的运输层协议 2)每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的(一对一) 3)TCP提供可靠交付的服务 4)TCP提供全双工通信 5)面向字节流:T ...
- HDU 5303 Delicious Apples (贪心 枚举 好题)
Delicious Apples Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Other ...
- java克隆对象clone()的使用方法和作用
转自:997.html">http://www.okrs.cn/blog/news/?997.html 内容摘要 若需改动一个对象,同一时候不想改变调用者的对象.就要制作该对象的一个本 ...
- I2C上拉电阻取值范围
I2C总线是微电子通信控制领域中常用的一种总线标准,具备接线少,控制简单,速率高等优点.在I2C电路中常见的上拉电阻有1k.1.5k.2.2k.4.7k.5.1k.10k等等,但是应该如何根据开发要求 ...
- “var arr = []; ”和 “var arr = {};” 的差别
1.面试题 var arr = []; var arr = {}; 比較上述代码有什么差别? 2.解析 var arr = [];是一个数组对象 var arr = {} ...
- 书评第003篇:《0day安全:软件漏洞分析技术(第2版)》
本书基本信息 丛书名:安全技术大系 作者:王清(主编),张东辉.周浩.王继刚.赵双(编著) 出版社:电子工业出版社 出版时间:2011-6-1 ISBN:9787121133961 版次:1 页数:7 ...
- Android之弹出多级菜单
使用布局文件创建菜单:(多级菜单) 在res下创建目录menu(假设已经有啦就不用再创建了) 在该menu目录下创建XML文件这里我把文件名称命名为menu 在创建的menu.XML文件里 写入: & ...
- PHP使用debug_backtrace方法跟踪代码调用
在开发过程中,例如要修改别人开发的代码或调试出问题的代码,需要对代码流程一步步去跟踪,找到出问题的地方进行修改.如果有一个方法可以获取到某段代码是被哪个方法调用,并能一直回溯到最开始调用的地方(包括调 ...
- 在webkit中如何避免触发layout(重排)
很多web开发者都已经意识到,在脚本执行中,DOM操作的用时可能比js本身执行时间要长很多,其中潜在的消耗基本上是由于触发了layout(即重排reflow:由DOM树构建为Render渲染树的过程) ...