【BZOJ 3387】 线段树= =
57 跨栏训练
为了让奶牛参与运动,约翰建造了 K 个栅栏。每条栅栏可以看做是二维平面上的一条线段,它
们都平行于 X 轴。第 i 条栅栏所覆盖的 X 轴坐标的区间为 [ Ai,Bi ], Y 轴高度就是 i。一开始,奶牛
在坐标 (S,K + 1) 处,它们的家在原点处,所以要想要回家就必须“跨”一些栅栏。
但奶牛们是跨不过栅栏的,它们只能绕过栅栏。在二维平面上,它们只能沿水平和垂直方向移动,
如果前进的道路上出现栅栏,它们就不能前进,必须沿水平方向移动到没有栅栏的地方再前进。奶牛
们希望走的路越短越好,由于在垂直方向上的路程是确定的,你只需要帮它们求出在水平方向的最短
路程就可以了。
输入格式
• 第一行:两个整数 K 和 S, 1 ≤ K ≤ 50000, − 105 ≤ S ≤ 105
• 第二行到第 N + 1 行:第 i + 1 行有两个整数 Ai 和 Bi, − 105 ≤ Ai ≤ Bi ≤ 105
输出格式
• 单个整数:表示奶牛从起点到终点在水平方向移动的最短总距离
样例输入
4 0
-2 1
-1 2
-3 0
-2 1
样例输出
4
解释
第四个栅栏是最先遇到的,向右移一格绕过
它。为了绕过第二个栅栏,再向右移一格,最后
为了回到原点向左移两格
【分析】
就是,差不多,像是个模拟的东西,如果没有东西挡着你,就不用走了(如果要走,等一下有东西挡着你再走)、
如果有东西挡着你,就走到栅栏左边或者栅栏右边(不用多走,要是需要多走,等一下再走)
但是询问区间的话每个点到栅栏左端点需要加的距离是不一样的,所以我们维护的时候不是他走的距离,而是他走的距离在加上他走到图的最左边的距离。
右边也一样。
就是一个区间修改成INF的操作 以及单点修改 还有区间查询。
代码如下:
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 200010
#define Maxk 50010
#define INF 0xfffffff int a[Maxk],b[Maxk]; struct node
{
int l,r,lc,rc,a1,a2;
bool lazy;
}t[Maxn*];int len; int mymin(int x,int y) {return x<y?x:y;}
int mymax(int x,int y) {return x>y?x:y;}
int mn=INF,mx=; int build(int l,int r)
{
int x=++len;
t[x].l=l;t[x].r=r;t[x].a1=t[x].a2=INF;
t[x].lazy=;
if(l!=r)
{
int mid=(l+r)>>;
t[x].lc=build(l,mid);
t[x].rc=build(mid+,r);
}
return x;
} void upd(int x)
{
if(t[x].lazy==) return;
if(t[x].l!=t[x].r)
{
int lc=t[x].lc,rc=t[x].rc;
t[lc].lazy=;t[rc].lazy=;
}
t[x].a1=t[x].a2=INF;
t[x].lazy=;
} void change(int x,int l,int r)
{
if(l>r) return;
upd(x);
if(t[x].l==l&&t[x].r==r)
{
t[x].lazy=;
return;
}
int mid=(t[x].l+t[x].r)>>;
if(r<=mid) change(t[x].lc,l,r);
else if(l>mid) change(t[x].rc,l,r);
else
{
change(t[x].lc,l,mid);
change(t[x].rc,mid+,r);
}
int lc=t[x].lc,rc=t[x].rc;
upd(lc);upd(rc);
t[x].a1=mymin(t[lc].a1,t[rc].a1);
t[x].a2=mymin(t[lc].a2,t[rc].a2);
} void change2(int x,int y,int z)
{
upd(x);
if(t[x].l==t[x].r)
{
t[x].a1=mymin(t[x].a1,z+y);
t[x].a2=mymin(t[x].a2,z+mx-y);
return;
}
int mid=(t[x].l+t[x].r)>>;
if(y<=mid) change2(t[x].lc,y,z);
else change2(t[x].rc,y,z);
int lc=t[x].lc,rc=t[x].rc;
upd(lc);upd(rc);
t[x].a1=mymin(t[lc].a1,t[rc].a1);
t[x].a2=mymin(t[lc].a2,t[rc].a2);
} int query(int x,int l,int r,bool p)
{
if(l>r) return INF;
upd(x);
if(t[x].l==l&&t[x].r==r)
{
if(!p) return t[x].a1;
else return t[x].a2;
}
int mid=(t[x].l+t[x].r)>>;
if(r<=mid) return query(t[x].lc,l,r,p);
else if(l>mid) return query(t[x].rc,l,r,p);
else return mymin(query(t[x].lc,l,mid,p),query(t[x].rc,mid+,r,p));
} int main()
{
int k,s;
scanf("%d%d",&k,&s);
for(int i=;i<=k;i++)
{
scanf("%d%d",&a[i],&b[i]);
mn=mymin(mn,a[i]);
mx=mymax(mx,b[i]);
}
mn=-mn+;
for(int i=;i<=k;i++) a[i]+=mn,b[i]+=mn;
mx+=mn;
len=;
build(,mx);
change2(,+mn,);
for(int i=;i<=k;i++)
{
int n1=query(,a[i]+,b[i]-,),n2=query(,a[i]+,b[i]-,);
if(n1!=INF) change2(,a[i],n1-a[i]);
if(n2!=INF) change2(,b[i],n2-(mx-b[i]) );
change(,a[i]+,b[i]-); }
s+=mn;
int ans=mymin(query(,,s,)-(mx-s),query(,s,mx,)-s);
printf("%d\n",ans);
return ;
}
[BZOJ 3387]
2016-10-31 15:17:12
【BZOJ 3387】 线段树= =的更多相关文章
- BZOJ 1798 (线段树||分块)的标记合并
我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...
- bzoj 3999 线段树区间提取 有序链剖
看错题目了,想成每个城市都可以买一个东西,然后在后面的某个城市卖掉,问最大收益.这个可以类似维护上升序列的方法在O(nlog^3n)的时间复杂度内搞定 这道题用到的一些方法: 1. 可以将有关的线段提 ...
- bzoj 3211 线段树
开方操作最多进行5次就可以把出现的任何数变成1. 所以用线段树暴力修改,以后修改时只需看一下是否当前区间都是0或1,如果是那么就直接返回. /***************************** ...
- bzoj 1018 线段树维护连通性
本题将一道LCT的题特殊化(支持加边和删边,询问图的连通性),将图变成了2×m的网格图,然后就神奇地可以用线段树来维护. 对于每个区间[l,r],维护其四个角落之间的连通性(仅仅通过[l,r]这段的边 ...
- bzoj 3212 线段树
裸的线段树 /************************************************************** Problem: User: BLADEVIL Langua ...
- bzoj 2120 线段树套平衡树
先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心..... 首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有, 但是能给我们一 ...
- bzoj 1901 线段树套平衡树+二分答案查询
我们就建一颗线段树,线段树的每一个节点都是一颗平衡树,对于每个询问来说,我们就二分答案, 查询每个二分到的mid在这个区间里的rank,然后就行了 /************************* ...
- BZOJ 1012 线段树||单调队列
非常裸的线段树 || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件 ...
- BZOJ 3681 线段树合并+网络流
思路: 暴力建图有n*m条边 考虑怎么优化 (那就只能加个线段树了呗) 然后我就不会写了..... 抄了一波题解 //By SiriusRen #include <bits/stdc++.h&g ...
- BZOJ 4756 线段树合并(线段树)
思路: 1.最裸的线段树合并 2. 我们可以观察到子树求一个东西 那我们直接DFS序好了 入队的时候统计一下有多少比他大的 出的时候统计一下 减一下 搞定~ 线段树合并代码: //By SiriusR ...
随机推荐
- Debian 6解决中文乱码
DEBIAN下中文显示 一.首先检查LOCALE情况 说明:DEBIAN因为基于GNU所以,对不同地域进行了不同的包支持,以LOCALE形式存在. 1.挂载ISO文件包,前8个ISO包就可以(这里不在 ...
- AWS RDS 使用笔记
创建VPC安全组 添加VPC子网 创建RDS子网组 创建RDS参数组 创建MySQL实例 查看RDS终端节点 使用 MySQL 监视器与数据库实例上的数据库连接 安装mysql client $ su ...
- 微信公众号支付(三):页面调用微信支付JS并完成支付
一.调用微信的JS文件 1.首先要绑定[JS接口安全域名],“公众号设置”的“功能设置”中 2.引入JS文件 备注:支持使用 AMD/CMD 标准模块加载方法加载 <script type=&q ...
- 20160324 javaweb 之request
package com.dzq.servlet; import java.io.IOException; import javax.servlet.ServletException; import j ...
- EqualsBuilder和HashCodeBuilder(重写equal和hashcode)
EqualsBuilder和HashCodeBuilder 自动化hashCode()和equals() 问题产生:当需要自动实现hashCode()和equals()方法 解决方法:使用Equa ...
- Entity Framework 的事务 DbTransaction
事务代码实现如下: public static void Transaction() { myitEntities entity = null; DbTransaction tran = null; ...
- 开发错误日志之Unix/Linux命令未执行或无结果等且程序无错误
在Unix/Linux环境中开发时,特别要注意权限问题,否则经常找不到错误的原因,其实就是因为权限所致.
- rgba兼容IE系列
在容器里面如果用到opacity或者filter:opacity里面的内容也会被滤镜化 如果不想里面的内容也被滤镜化我们可以用rgba来处理或者用透明的背景图片. 兼容ie的rgba的写法 backg ...
- PHP对URL设置
一.URL规则 1.默认是区分大小写的 2.如果我们不想区分大小写可以改配置文件 'URL_CASE_INSENSITIVE'=>true, //url不区分 ...
- C++相关资源
http://www.cnblogs.com/xi52qian/p/4186983.html语言ISO/IEC JTC1/SC22/WG21 - The C++ Standards Committee ...