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

题目传送门 - CF781E

题意

  有一个矩形,宽为 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 <bits/stdc++.h>
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<b.h;
}
vector <int> 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 <int> &s,int x){
while (a[s.back()].m<a[x].m)
s.pop_back();
s.push_back(x);
}
void update(int rt,int L,int R,int xL,int xR,int d){
if (L>xR||R<xL)
return;
if (xL<=L&&R<=xR){
Push(s[rt],d);
return;
}
int mid=(L+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 <int> &s,int h){
while (a[s.back()].m<h)
s.pop_back();
return s.back();
}
int query(int rt,int L,int R,int x,int d){
int ans=query(s[rt],d);
if (L==R)
return ans;
int mid=(L+R)>>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;
}

  

Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈的更多相关文章

  1. CodeForces 781E Andryusha and Nervous Barriers 线段树 扫描线

    题意: 有一个\(h \times w\)的矩形,其中有\(n\)个水平的障碍.从上往下扔一个小球,遇到障碍后会分裂成两个,分别从障碍的两边继续往下落. 如果从太高的地方落下来,障碍会消失. 问从每一 ...

  2. Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)

    Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...

  3. 洛谷P4425 转盘 [HNOI/AHOI2018] 线段树+单调栈

    正解:线段树+单调栈 解题报告: 传送门! 1551又是一道灵巧连题意都麻油看懂的题,,,,所以先解释一下题意好了,,,, 给定一个n元环 可以从0时刻开始从任一位置出发 每次可以选择向前走一步或者在 ...

  4. 线段树+单调栈+前缀和--2019icpc南昌网络赛I

    线段树+单调栈+前缀和--2019icpc南昌网络赛I Alice has a magic array. She suggests that the value of a interval is eq ...

  5. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  6. [Codeforces1132G]Greedy Subsequences——线段树+单调栈

    题目链接: Codeforces1132G 题目大意:给定一个序列$a$,定义它的最长贪心严格上升子序列为$b$满足若$a_{i}$在$b$中则$a_{i}$之后第一个比它大的也在$b$中.给出一个数 ...

  7. BZOJ.4540.[HNOI2016]序列(莫队/前缀和/线段树 单调栈 RMQ)

    BZOJ 洛谷 ST表的一二维顺序一定要改过来. 改了就rank1了哈哈哈哈.自带小常数没办法. \(Description\) 给定长为\(n\)的序列\(A_i\).\(q\)次询问,每次给定\( ...

  8. AtCoder Regular Contest 063 F : Snuke’s Coloring 2 (线段树 + 单调栈)

    题意 小 \(\mathrm{C}\) 很喜欢二维染色问题,这天他拿来了一个 \(w × h\) 的二维平面 , 初始时均为白色 . 然后他在上面设置了 \(n\) 个关键点 \((X_i , Y_i ...

  9. cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)

    题意: 给出n个三元组 e[i]=(si,ti,wi) 第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件: 1.j<i 2.tj<ti 3.sj<si 4.不存在j< ...

随机推荐

  1. 响应式页面-@media介绍

    01 响应式页面-@media介绍,   我们为什么要写自适应的页面(响应式页面) 众所周知,电脑.平板.手机的屏幕是差距很大的,假如在电脑上写好了一个页面,在电脑上看起来不错,但是如果放到手机上的话 ...

  2. 前端 ----- 01 -html介绍和head标签

    01-html介绍和head标签   主要内容 web标准 浏览器介绍 开发工具介绍 HTML介绍 HTML颜色介绍 HTML规范 HTML结构详解 一.web标准 web准备介绍: w3c:万维网联 ...

  3. [转] 为什么说 Java 程序员必须掌握 Spring Boot ?

    Spring Boot 2.0 的推出又激起了一阵学习 Spring Boot 热,那么, Spring Boot 诞生的背景是什么?Spring 企业又是基于什么样的考虑创建 Spring Boot ...

  4. mysql8:caching-sha2-password问题

    参考文章:https://blog.csdn.net/u010026255/article/details/80062153 问题:caching-sha2-password 处理: ALTER US ...

  5. mtu简单说明

    总结:本地的mtu值==网络设备的mtu值是最优的,一般本地和网络设备的默认值都是1500(字节),没什么特殊需求,尽量不要修改 一.什么是 MTU 值   1 从字面上来说,MTU 是英文 Maxi ...

  6. 洛谷P5219 无聊的水题 I [prufer序列,生成函数,NTT]

    传送门 思路 有标号无根树的计数,还和度数有关,显然可以想到prufer序列. 问题就等价于求长度为\(n-2\),值域为\([1,n]\),出现次数最多的恰好出现\(m-1\)次,这样的序列有哪些. ...

  7. 2018 github热门项目

    github流行的几个项目,我们来学习一下. 1. developer-roadmap-chinese image.png 项目简介:2018年web程序员路线中文版, 这个仓库里包含了一些前端,后端 ...

  8. Confluence 6 配置时间和日期格式

    你可以修改你 Confluence 为用户显示的时期和时间格式.设置的句法使用的是 SimpleDateFormat class,请参考 Java SimpleDateFormat 文档中的内容来设置 ...

  9. Confluence 6 从关闭的连接中恢复

    当数据库服务器进行重启或者因为网络问题导致连接中断.所有在数据库连接池中的连接都会被中断.希望处理这个问题,通常需要 Confluence 进行重启. 但是,数据库连接池中的连接可以通过运行 SQL ...

  10. Confluence 6 数据库 JDBC 驱动

    本页面提供了支持的数据库的所有 JDBC 驱动下载链接. 基于许可证的原因,我们没有将 MySQL 或 Oracle 的数据库驱动整合到 Confluence 中,因此你需要在 Confluence ...