博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈
阅读量:5015 次
发布时间:2019-06-12

本文共 2556 字,大约阅读时间需要 8 分钟。

原文链接https://www.cnblogs.com/zhouzhendong/p/CF781E.html

题意

  有一个矩形,宽为 w ,高为 h 。一开始会有 w 个球分别从高处的每一个位置开始下落。

  有 n 个挡板,每一个挡板有 4 个属性,分别是 u,L,R,s ,表示当前挡板的高度为 u ,横向覆盖的区间为 L,R ,如果球从高度大于 u+s 的地方开始下落到当前挡板,那么球会穿透当前挡板,否则球会分裂成两个,分别从该挡板的两边从新开始下落(如图的第一行),特殊地,当挡板的一段在边界上时,分裂得到的两个球都会从另一端下降(如图的第二行)。

  问最终地面上能收到多少个球。

  $w,n\leq 10^5,\ \ \  u,s,h\leq 10^9,\ \ 1\leq L\leq R\leq n$,保证每一行最多只有一个挡板,且不会有挡板两端都到达了边界。

    

 

题解

  首先,我们观察到如果直接 dp ,转移数就等于 挡板数×2+w (每一个挡板的两侧以及一开始投放的 w 个球)。

  关键在于如何找到一个球从每一个位置开始下落会在哪里分裂。

  我们来理一理思路:

  我们要找的挡板要满足以下条件:

    1. 高度小于当前高度。

    2. u+s 要大于等于当前高度。

    3. [L,R] 要包含当前横坐标。

    4. 在满足上述条件的情况下,使得 u 最大。

  显然可以发现可以树套树套树。但是这样显然不足以通过此题。

  然后我们发现只需要把挡板按照高度从低到高排序,然后依次操作就好了,这样只需要树套树。但是这样的空间复杂度仍然是凉凉的。

  于是,接下来是最重要的一步了!

  一个挡板的纵向影响区间是 [u,u+s] ,对于这一维,我们可以直接用单调栈维护。

  于是我们得到一个 线段树 + 单调栈的做法。可以通过本题。

  时间复杂度 $O(n\log n)$ 。  

代码

#include 
using namespace std;typedef long long LL;LL read(){ LL x=0,f=1; char ch=getchar(); while (!isdigit(ch)&&ch!='-') ch=getchar(); if (ch=='-') f=-1,ch=getchar(); while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return x*f;}const int N=100005,mod=1e9+7;int n,h,w;struct Node{ int L,R,h,m,ans;}a[N];bool cmph(Node a,Node b){ return a.h
s[N<<2];void build(int rt,int L,int R){ s[rt].push_back(1); if (L==R) return; int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; build(ls,L,mid); build(rs,mid+1,R);}void Push(vector
&s,int x){ while (a[s.back()].m
xR||R
>1,ls=rt<<1,rs=ls|1; update(ls,L,mid,xL,xR,d); update(rs,mid+1,R,xL,xR,d);}int query(vector
&s,int h){ while (a[s.back()].m
>1,ls=rt<<1,rs=ls|1; if (x<=mid) return max(ans,query(ls,L,mid,x,d)); else return max(ans,query(rs,mid+1,R,x,d));}int main(){ h=read(),w=read(),n=read(); for (int i=1;i<=n;i++){ a[i].h=read(),a[i].L=read(),a[i].R=read(); a[i].m=min(a[i].h+read(),(LL)h+1); } n++; a[n].h=0,a[n].L=1,a[n].R=w,a[n].m=1.05e9; sort(a+1,a+n+1,cmph); a[1].ans=1; for (int i=0;i<(N<<2);i++) s[i].clear(); build(1,1,w); for (int i=2;i<=n;i++){ if (a[i].L==1) a[i].ans=2*a[query(1,1,w,a[i].R+1,a[i].h)].ans%mod; else if (a[i].R==w) a[i].ans=2*a[query(1,1,w,a[i].L-1,a[i].h)].ans%mod; else a[i].ans=(a[query(1,1,w,a[i].L-1,a[i].h)].ans +a[query(1,1,w,a[i].R+1,a[i].h)].ans)%mod; update(1,1,w,a[i].L,a[i].R,i); } int ans=0; for (int i=1;i<=w;i++) ans=(ans+a[query(1,1,w,i,h+1)].ans)%mod; printf("%d",ans); return 0;}

  

转载于:https://www.cnblogs.com/zhouzhendong/p/CF781E.html

你可能感兴趣的文章
58. Length of Last Word(js)
查看>>
前端面试题汇总(持续更新...)
查看>>
如何成为F1车手?
查看>>
QT自定义消息
查看>>
Save (Not Permitted) Dialog Box
查看>>
装饰模式(Decorator)
查看>>
任务13:在Core Mvc中使用Options
查看>>
利用Excel 2010数据透视图实现数字的可视化的图形直观展示
查看>>
Sort Colors
查看>>
iview树的修改某个节点,树刷新后自动展开你刚才展开的所有节点
查看>>
oracle服务起不来以及无法监听问题解决
查看>>
Mvc--Html.ActionLink()的用法
查看>>
delphi 基础书籍推荐
查看>>
《面向对象程序设计》2018年春学期寒假及博客作业总结
查看>>
iOS开发UI之KVC(取值/赋值) - KVO (观察某个对象的某个属性的改变)
查看>>
1.7 将一个MxN矩阵所有为0的元素所在行和列全部置0
查看>>
删除U盘时提示无法停止‘通用卷’设备的解决方法!!不要每次都硬拔了,对电脑有不小的损害!!!...
查看>>
Java中接口与接口和类之间的关系
查看>>
芯片TPS70925
查看>>
linux shell 发送email 附件
查看>>