【CF720D】Slalom

题意:一个n*m的网格,其中有k个矩形障碍,保证这些障碍不重叠。问你从(1,1)走到(n,m),每步只能往右或往上走,不经过任何障碍的方案数。两种方案被视为不同,当且仅当存在一个障碍,它在第一种方案里被从右侧绕过,而在第二种方案里被从左侧绕过(第一种左,第二种右同理)。

$n,m\le 10^6,k\le 10^5$。

题解:首先我们将相同方案的不同路线放到一起,并用其中最低的那个路线来代表这个方案。然后考虑扫描线,当新加入一个障碍的左侧时,这个侧面以左的所有路线都被迫走到这个障碍的上沿处。用线段树维护一下就好,细节比较多。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. #define lson x<<1
  6. #define rson x<<1|1
  7. using namespace std;
  8. typedef long long ll;
  9. const int P=1000000007;
  10. const int maxk=100010;
  11. const int maxn=1000010;
  12. int n,m,k,tot;
  13. struct node
  14. {
  15. int x,l,r,k;
  16. }p[maxk*3];
  17. int s[maxn<<2],tag[maxn<<2],siz[maxn<<2];
  18. bool cmp(const node &a,const node &b)
  19. {
  20. return (a.x==b.x)?((a.k==b.k)?(a.l>b.l):(a.k<b.k)):(a.x<b.x);
  21. }
  22. inline void pushdown(int l,int r,int x)
  23. {
  24. if(tag[x]==1)
  25. {
  26. s[lson]=s[rson]=0,tag[lson]=tag[rson]=1;
  27. int mid=(l+r)>>1;
  28. siz[lson]=mid-l+1,siz[rson]=r-mid,tag[x]=0;
  29. }
  30. if(tag[x]==2)
  31. {
  32. s[lson]=s[rson]=0,tag[lson]=tag[rson]=2,siz[lson]=siz[rson]=0,tag[x]=0;
  33. }
  34. }
  35. inline void pushup(int x)
  36. {
  37. s[x]=s[lson]+s[rson],siz[x]=siz[lson]+siz[rson];
  38. if(s[x]>=P) s[x]-=P;
  39. }
  40. void modify(int l,int r,int x,int a,int b)
  41. {
  42. if(l==r)
  43. {
  44. s[x]=b;
  45. return ;
  46. }
  47. pushdown(l,r,x);
  48. int mid=(l+r)>>1;
  49. if(a<=mid) modify(l,mid,lson,a,b);
  50. else modify(mid+1,r,rson,a,b);
  51. pushup(x);
  52. }
  53. void updata(int l,int r,int x,int a,int b,int c)
  54. {
  55. if(a<=l&&r<=b)
  56. {
  57. if(c==1) tag[x]=1,siz[x]=r-l+1,s[x]=0;
  58. else tag[x]=2,siz[x]=s[x]=0;
  59. return ;
  60. }
  61. pushdown(l,r,x);
  62. int mid=(l+r)>>1;
  63. if(a<=mid) updata(l,mid,lson,a,b,c);
  64. if(b>mid) updata(mid+1,r,rson,a,b,c);
  65. pushup(x);
  66. }
  67. int query(int l,int r,int x,int a,int b)
  68. {
  69. if(a<=l&&r<=b) return s[x];
  70. pushdown(l,r,x);
  71. int mid=(l+r)>>1,ret=0;
  72. if(a<=mid) ret+=query(l,mid,lson,a,b);
  73. if(b>mid) ret+=query(mid+1,r,rson,a,b);
  74. if(ret>=P) ret-=P;
  75. return ret;
  76. }
  77. int count(int l,int r,int x,int a,int b)
  78. {
  79. if(a<=l&&r<=b) return siz[x];
  80. pushdown(l,r,x);
  81. int mid=(l+r)>>1;
  82. if(b<=mid) return count(l,mid,lson,a,b);
  83. if(a>mid) return count(mid+1,r,rson,a,b);
  84. return count(l,mid,lson,a,b)+count(mid+1,r,rson,a,b);
  85. }
  86. int find(int l,int r,int x,int a)
  87. {
  88. if(l==r) return l;
  89. pushdown(l,r,x);
  90. int mid=(l+r)>>1;
  91. if(a<=siz[lson]) return find(l,mid,lson,a);
  92. return find(mid+1,r,rson,a-siz[lson]);
  93. }
  94. inline int rd()
  95. {
  96. int ret=0,f=1; char gc=getchar();
  97. while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
  98. while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
  99. return ret*f;
  100. }
  101.  
  102. int main()
  103. {
  104. //freopen("cf720D.in","r",stdin);
  105. n=rd(),m=rd(),k=rd();
  106. int i,a,b,c,d;
  107. for(i=1;i<=k;i++)
  108. {
  109. a=rd(),b=rd(),c=rd(),d=rd();
  110. p[++tot].x=a,p[tot].l=b,p[tot].r=d,p[tot].k=2;
  111. p[++tot].x=a+1,p[tot].l=b,p[tot].r=d,p[tot].k=1;
  112. p[++tot].x=c+1,p[tot].l=b,p[tot].r=d,p[tot].k=3;
  113. }
  114. p[++tot].x=1,p[tot].l=2,p[tot].r=m,p[tot].k=1;
  115. p[++tot].x=1,p[tot].l=2,p[tot].r=m,p[tot].k=3;
  116. p[++tot].x=n+1,p[tot].l=1,p[tot].r=m-1,p[tot].k=2;
  117. sort(p+1,p+tot+1,cmp);
  118. modify(1,m,1,1,1);
  119. for(a=1;a<=tot;a=b+1)
  120. {
  121. for(b=a;b<tot&&p[b+1].x==p[b].x&&p[b+1].k==p[b].k;b++);
  122. if(p[a].k==2)
  123. {
  124. for(i=a;i<=b;i++) if(p[i].r!=m)
  125. {
  126. c=count(1,m,1,1,p[i].r+1);
  127. if(!c) d=0;
  128. else d=find(1,m,1,c);
  129. if(d!=p[i].r+1)
  130. {
  131. modify(1,m,1,p[i].r+1,query(1,m,1,d+1,p[i].r+1));
  132. }
  133. }
  134. }
  135. else if(p[a].k==1)
  136. {
  137. for(i=a;i<=b;i++) updata(1,m,1,p[i].l,p[i].r,1);
  138. }
  139. else
  140. {
  141. for(i=a;i<=b;i++) updata(1,m,1,p[i].l,p[i].r,2);
  142. }
  143. }
  144. printf("%d",query(1,m,1,m,m));
  145. return 0;
  146. }

【CF720D】Slalom 扫描线+线段树的更多相关文章

  1. HDU 3642 - Get The Treasury - [加强版扫描线+线段树]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3642 Time Limit: 10000/5000 MS (Java/Others) Memory L ...

  2. 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树

    [BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...

  3. 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 ...

  4. 【bzoj4491】我也不知道题目名字是什么 离线扫描线+线段树

    题目描述 给定一个序列A[i],每次询问l,r,求[l,r]内最长子串,使得该子串为不上升子串或不下降子串 输入 第一行n,表示A数组有多少元素接下来一行为n个整数A[i]接下来一个整数Q,表示询问数 ...

  5. hdu1542 Atlantis(扫描线+线段树+离散)矩形相交面积

    题目链接:点击打开链接 题目描写叙述:给定一些矩形,求这些矩形的总面积.假设有重叠.仅仅算一次 解题思路:扫描线+线段树+离散(代码从上往下扫描) 代码: #include<cstdio> ...

  6. P3722 [AH2017/HNOI2017]影魔(单调栈+扫描线+线段树)

    题面传送门 首先我们把这两个贡献翻译成人话: 区间 \([l,r]\) 产生 \(p_1\) 的贡献当且仅当 \(a_l,a_r\) 分别为区间 \([l,r]\) 的最大值和次大值. 区间 \([l ...

  7. BZOJ 2584: [Wc2012]memory(扫描线+线段树)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=2584 题意:给出平面n个线段,任意两个线段严格不相交,且每个线段不平行于坐标轴.移 ...

  8. [BZOJ 1218] [HNOI2003] 激光炸弹 【n logn 做法 - 扫描线 + 线段树】

    题目链接:BZOJ - 1218 题目分析 可以覆盖一个边长为 R 的正方形,但是不能包括边界,所以等价于一个边长为 R - 1 的正方形. 坐标范围 <= 5000 ,直接 n^2 的二维前缀 ...

  9. hdu4419 Colourful Rectangle 12年杭州网络赛 扫描线+线段树

    题意:给定n个矩形,每个矩形有一种颜色,RGB中的一种.相交的部分可能为RG,RB,GB,RGB,问这n个矩形覆盖的面积中,7种颜色的面积分别为多少 思路:把x轴离散化做扫描线,线段树维护一个扫描区间 ...

随机推荐

  1. 非抢占式RCU实现(一)

    关于RCU的实现,考虑如下情形: 1.非抢占式RCU 2.限于嵌入式系统4核.每核单线程 3.RCU_FANOUT = 32 此时,RCU_TREE退化为单节点,如下,针对rcu_sched_stat ...

  2. perforce变量配置与使用

    linux Perforce 使用 1.配置环境变量: 下载  perforce    放到/usr/bin/下 export P4PORT=192.168.4.88:1666 #P4所在的主机exp ...

  3. [转]好文章:Android的AlertDialog详解

    refer:http://www.2cto.com/kf/201205/131876.html AlertDialog的构造方法全部是Protected的,所以不能直接通过new一个AlertDial ...

  4. Android ROM 打包记录

    android5.1平板或手机应用层一些常用的修改项及目录所在: 1.所以系统应用所在的目录: \alps\packages\apps 2.一些系统属性的定义:并且可以仿写自行定义变量 \alps\b ...

  5. 8 -- 深入使用Spring -- 2...2 指定Bean的作用域

    8.2.2 指定Bean的作用域 当使用XML 配置方式来配置Bean实例时,可以通过scope来指定Bean实例的作用域,没有指定scope属性的Bean实例作用域默认是singleton. 当采用 ...

  6. 18个不常见的C#关键字,您使用过几个?

    转自:http://www.cnblogs.com/zhuqil/archive/2010/04/09/UnCommon-Csharp-keywords-A-Look.html 1.__arglist ...

  7. mac开机启动apache、memcached与mysql

    一.开机自动启动apache方法 #sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist //开机启动 ...

  8. 查询mssql 密码

    select name,password from syslogins Select master.dbo.fn_varbintohexstr(password_hash) from sys.sql_ ...

  9. RF实现多次失败重跑结果合并的基础方法和优化方法

    实现思路:通过分次执行失败案例重跑,然后通过结果文件合并命令实现多次失败重跑结果文件的合并,并输出合并后的log和report文件: 说明:具体失败案例重跑命令和结果文件合并命令请参考本博客其他相关章 ...

  10. 使用 Selenium

    Selenium 简介 Selenium 基本用法 Selenium 查找节点 Selenium 节点交互 Selenium 动作链 Selenium 执行 JavaScript Selenium 获 ...