【CF720D】Slalom 扫描线+线段树
【CF720D】Slalom
题意:一个n*m的网格,其中有k个矩形障碍,保证这些障碍不重叠。问你从(1,1)走到(n,m),每步只能往右或往上走,不经过任何障碍的方案数。两种方案被视为不同,当且仅当存在一个障碍,它在第一种方案里被从右侧绕过,而在第二种方案里被从左侧绕过(第一种左,第二种右同理)。
$n,m\le 10^6,k\le 10^5$。
题解:首先我们将相同方案的不同路线放到一起,并用其中最低的那个路线来代表这个方案。然后考虑扫描线,当新加入一个障碍的左侧时,这个侧面以左的所有路线都被迫走到这个障碍的上沿处。用线段树维护一下就好,细节比较多。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lson x<<1
#define rson x<<1|1
using namespace std;
typedef long long ll;
const int P=1000000007;
const int maxk=100010;
const int maxn=1000010;
int n,m,k,tot;
struct node
{
int x,l,r,k;
}p[maxk*3];
int s[maxn<<2],tag[maxn<<2],siz[maxn<<2];
bool cmp(const node &a,const node &b)
{
return (a.x==b.x)?((a.k==b.k)?(a.l>b.l):(a.k<b.k)):(a.x<b.x);
}
inline void pushdown(int l,int r,int x)
{
if(tag[x]==1)
{
s[lson]=s[rson]=0,tag[lson]=tag[rson]=1;
int mid=(l+r)>>1;
siz[lson]=mid-l+1,siz[rson]=r-mid,tag[x]=0;
}
if(tag[x]==2)
{
s[lson]=s[rson]=0,tag[lson]=tag[rson]=2,siz[lson]=siz[rson]=0,tag[x]=0;
}
}
inline void pushup(int x)
{
s[x]=s[lson]+s[rson],siz[x]=siz[lson]+siz[rson];
if(s[x]>=P) s[x]-=P;
}
void modify(int l,int r,int x,int a,int b)
{
if(l==r)
{
s[x]=b;
return ;
}
pushdown(l,r,x);
int mid=(l+r)>>1;
if(a<=mid) modify(l,mid,lson,a,b);
else modify(mid+1,r,rson,a,b);
pushup(x);
}
void updata(int l,int r,int x,int a,int b,int c)
{
if(a<=l&&r<=b)
{
if(c==1) tag[x]=1,siz[x]=r-l+1,s[x]=0;
else tag[x]=2,siz[x]=s[x]=0;
return ;
}
pushdown(l,r,x);
int mid=(l+r)>>1;
if(a<=mid) updata(l,mid,lson,a,b,c);
if(b>mid) updata(mid+1,r,rson,a,b,c);
pushup(x);
}
int query(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b) return s[x];
pushdown(l,r,x);
int mid=(l+r)>>1,ret=0;
if(a<=mid) ret+=query(l,mid,lson,a,b);
if(b>mid) ret+=query(mid+1,r,rson,a,b);
if(ret>=P) ret-=P;
return ret;
}
int count(int l,int r,int x,int a,int b)
{
if(a<=l&&r<=b) return siz[x];
pushdown(l,r,x);
int mid=(l+r)>>1;
if(b<=mid) return count(l,mid,lson,a,b);
if(a>mid) return count(mid+1,r,rson,a,b);
return count(l,mid,lson,a,b)+count(mid+1,r,rson,a,b);
}
int find(int l,int r,int x,int a)
{
if(l==r) return l;
pushdown(l,r,x);
int mid=(l+r)>>1;
if(a<=siz[lson]) return find(l,mid,lson,a);
return find(mid+1,r,rson,a-siz[lson]);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
} int main()
{
//freopen("cf720D.in","r",stdin);
n=rd(),m=rd(),k=rd();
int i,a,b,c,d;
for(i=1;i<=k;i++)
{
a=rd(),b=rd(),c=rd(),d=rd();
p[++tot].x=a,p[tot].l=b,p[tot].r=d,p[tot].k=2;
p[++tot].x=a+1,p[tot].l=b,p[tot].r=d,p[tot].k=1;
p[++tot].x=c+1,p[tot].l=b,p[tot].r=d,p[tot].k=3;
}
p[++tot].x=1,p[tot].l=2,p[tot].r=m,p[tot].k=1;
p[++tot].x=1,p[tot].l=2,p[tot].r=m,p[tot].k=3;
p[++tot].x=n+1,p[tot].l=1,p[tot].r=m-1,p[tot].k=2;
sort(p+1,p+tot+1,cmp);
modify(1,m,1,1,1);
for(a=1;a<=tot;a=b+1)
{
for(b=a;b<tot&&p[b+1].x==p[b].x&&p[b+1].k==p[b].k;b++);
if(p[a].k==2)
{
for(i=a;i<=b;i++) if(p[i].r!=m)
{
c=count(1,m,1,1,p[i].r+1);
if(!c) d=0;
else d=find(1,m,1,c);
if(d!=p[i].r+1)
{
modify(1,m,1,p[i].r+1,query(1,m,1,d+1,p[i].r+1));
}
}
}
else if(p[a].k==1)
{
for(i=a;i<=b;i++) updata(1,m,1,p[i].l,p[i].r,1);
}
else
{
for(i=a;i<=b;i++) updata(1,m,1,p[i].l,p[i].r,2);
}
}
printf("%d",query(1,m,1,m,m));
return 0;
}
【CF720D】Slalom 扫描线+线段树的更多相关文章
- HDU 3642 - Get The Treasury - [加强版扫描线+线段树]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...
- 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树
[BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...
- HDU 3265/POJ 3832 Posters(扫描线+线段树)(2009 Asia Ningbo Regional)
Description Ted has a new house with a huge window. In this big summer, Ted decides to decorate the ...
- 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树
题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...
- hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积
题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...
- P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)
题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...
- BZOJ 2584: [Wc2012]memory(扫描线+线段树)
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2584 题意:给出平面n个线段,任意两个线段严格不相交,且每个线段不平行于坐标轴.移 ...
- [BZOJ 1218] [HNOI2003] 激光炸弹 【n logn 做法 - 扫描线 + 线段树】
题目链接:BZOJ - 1218 题目分析 可以覆盖一个边长为 R 的正方形,但是不能包括边界,所以等价于一个边长为 R - 1 的正方形. 坐标范围 <= 5000 ,直接 n^2 的二维前缀 ...
- hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树
题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种.相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少 思路:把x轴离散化做扫描线,线段树维护一个扫描区间 ...
随机推荐
- 通过tarball形式安装HBASE Cluster(CDH5.0.2)——Hadoop NameNode HA 切换引起的Hbase错误,以及Hbase如何基于NameNode的HA进行配置
通过tarball形式安装HBASE Cluster(CDH5.0.2)——Hadoop NameNode HA 切换引起的Hbase错误,以及Hbase如何基于NameNode的HA进行配置 配置H ...
- UNIX环境编程学习笔记(17)——进程管理之进程的几个基本概念
lienhua342014-10-05 1 main 函数是如何被调用的? 在编译 C 程序时,C 编译器调用链接器在生成的目标可执行程序文件中,设置一个特殊的启动例程为程序的起始地址.当内核执行 C ...
- 内存管理 初始化(六)vmalloc_init 及 ioremap
是不是我错了,本想这个函数会如网上所说将进行非连续内存管理的初始化,但是对于2.6.34的ARM架构而言,该函数实际完成的业务非常少. 内存管理的初始化读到此处,我感觉原有的认识存在很大缺陷: (1) ...
- 小企业是否能用得上"ITIL"?
在小型IT部门中,明显存在着迫切的IT管理需求.但目前主流ITSM解决方案的价格.实施周期.复杂程度.对人力资源的占用等使他们难以承受. 浦发机械公司的计算机部经理老张带着十几个员工,经过数年 ...
- TIMEOUT HANDLING WITH HTTPCLIENT
https://www.thomaslevesque.com/2018/02/25/better-timeout-handling-with-httpclient/ The problem If yo ...
- GOF---Java开发中的23种设计模式详解
表点 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式 ...
- Python中的and/or
在Python中,可以通过and,or和not进行逻辑运算,下面就来看看and和or的简单介绍. 逻辑与-and 对于包含and运算的表达式,Python解释器将从左到右扫描,返回第一个为假的表达式值 ...
- X-WAF简单测试体验
X-WAF 最近才关注到的一款云WAF,花了一些时间搭建了一个环境,并做了一些测试,感觉比较适合新手来练习WAF Bypass. X-WAF是一款适用中.小企业的云WAF系统,让中.小企业也可以非常方 ...
- 运行RF测试案例,显示unable to open socket to "localhost:56505" error: [Errno 10061] 错误,且关闭RF卡死的解决办法
问题描述: 执行WEB ui测试案例后,执行请他的测试案例显示unable to open socket to "localhost:56505" error: [Errno 10 ...
- Ansible常用模块使用
Ansible官方提供了非常多的模块,还有若干第三方模块,我们也可以自己编写模块. Ansible对远程服务器的操作实际是通过模块完成的,先将模块拷贝到远程服务器,完成操作后,然后在远程服务器上删除该 ...