4422: [Cerc2015]Cow Confinement

Time Limit: 50 Sec  Memory Limit: 512 MB
Submit: 61  Solved: 26
[Submit][Status][Discuss]

Description

一个10^6行10^6列的网格图,上面有一些牛、花和一些矩形围栏,围栏在格子的边界上,牛和花在格子里,牛只能向下或向右走,牛也不能穿过围栏和地图边界,求每头牛它能到达的花的数量。注意栅栏不会相交
 
 

Input

第一行一个数f表示矩形围栏的数量。
接下来f行,每行四个数x1,y1,x2,y2,表示(x1,y1)在围栏内部矩形的左上角,(x2,y2)在右下角。
接下来一行一个数m表示花的数量。
接下来m行每行两个数x,y,表示在(x,y)处有一朵花。
接下来一行一个数n表示牛的数量。
接下来n行每行两个数x,y,表示在(x,y)处有一头牛。

Output

总共n行,每行一个数ans,第i个数表示第i头牛能到ans个花。

Sample Input

4
2 2 8 4
1 9 4 10
6 7 9 9
3 3 7 3
9
3 4
8 4
11 5
10 7
10 8
9 8
2 8
4 11
9 11
8
1 1
5 10
6 9
3 7
7 1
4 2
7 5
3 3

Sample Output

5
1
0
1
3
1
3
0

HINT

0<=f<=200000
0<=m<=200000
1<=n<=200000

Source

Solution

一道idea非常好的题

首先这题可以DP,不过转移之类的需要讨论,比较麻烦

$dp[i][j]=\begin{Bmatrix} 0(下面和右面都有栅栏)\\ dp[i+1][j](右面有栅栏)\\ dp[i][j+1](下面有栅栏)\\ dp[i+1][j]+dp[i][j+1]-dp[i+1][j+1]((i+1,j+1)不是栅栏的左上角)\\ dp[i+1][j]+dp[i][j+1]-dp[x+1][y+1]((i+1,j+1)是左上角,(x,y)是右下角)& & \end{Bmatrix}+flower[i][j]$

这样DP的时间复杂度是$O((N+F+M)^{2})$的

那么考虑优化这个DP

差分出$f[i][j]$表示$(i,j)$能得到,但$(i,j-1)$不能得到的花的数量

那么考虑扫描线,从右往左

那讨论一下各种情况,

遇到花单点数值+1;遇到一个未出现过的栅栏,区间查询和,单点修改数值,区间修改覆盖0;删除一个栅栏,区间修改覆盖0;遇见一头牛,找到下方第一个栅栏,区间求和;

显然都可以用线段树维护

查找下方第一个栅栏?维护一个最小即可

时间复杂度是$O(10^{6}log10^{6})$

实现起来有一些细节,线段树中需要加特判,当所需要修改的坐标为0啊之类的

Code

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<cstring>
  5. #include<cmath>
  6. using namespace std;
  7. inline int read()
  8. {
  9. int x=,f=; char ch=getchar();
  10. while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
  11. while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
  12. return x*f;
  13. }
  14. #define MAXY 1000000
  15. #define MAXF 200010
  16. #define MAXN 200010
  17. #define MAXM 200010
  18. int F,M,N;
  19. struct FenceNode{int x1,x2,y1,y2;}fen[MAXF];
  20. struct CowNode{int x,y,id;}cow[MAXN];
  21. struct FlowerNode{int x,y;}flo[MAXM];
  22. struct LineNode{int y,x1,x2,id,f;}line[MAXF<<]; int tp;
  23. struct SegmentTreeNode{int l,r,tag,bk,sum;}tree[MAXY<<];
  24. int tmp[MAXF],ans[MAXN];
  25. inline void Update(int now)
  26. {
  27. tree[now].bk=min(tree[now<<].bk,tree[now<<|].bk);
  28. tree[now].sum=tree[now<<].sum+tree[now<<|].sum;
  29. }
  30. inline void PushDown(int now)
  31. {
  32. if (!tree[now].tag || tree[now].l==tree[now].r) return;
  33. tree[now].tag=;
  34. tree[now<<].sum=; tree[now<<|].sum=;
  35. tree[now<<].tag=; tree[now<<|].tag=;
  36. }
  37. inline void BuildTree(int now,int l,int r)
  38. {
  39. tree[now].l=l,tree[now].r=r;
  40. tree[now].sum=; tree[now].tag=; tree[now].bk=MAXY;
  41. if (l==r) return;
  42. int mid=(l+r)>>;
  43. BuildTree(now<<,l,mid);
  44. BuildTree(now<<|,mid+,r);
  45. Update(now);
  46. }
  47. inline void PointChangeSum(int now,int pos,int D)
  48. {
  49. if (pos==MAXY+ || pos==) return;
  50. int l=tree[now].l,r=tree[now].r;
  51. PushDown(now);
  52. if (l==r) {tree[now].sum+=D; return;}
  53. int mid=(l+r)>>;
  54. if (pos<=mid) PointChangeSum(now<<,pos,D);
  55. if (pos>mid) PointChangeSum(now<<|,pos,D);
  56. Update(now);
  57. }
  58. inline void PointChangeBreak(int now,int pos,int D)
  59. {
  60. if (pos==MAXY+ || pos==) return;
  61. int l=tree[now].l,r=tree[now].r;
  62. PushDown(now);
  63. if (l==r) {tree[now].bk=D? l:MAXY; return;}
  64. int mid=(l+r)>>;
  65. if (pos<=mid) PointChangeBreak(now<<,pos,D);
  66. if (pos>mid) PointChangeBreak(now<<|,pos,D);
  67. Update(now);
  68. }
  69. inline void IntervalChange(int now,int L,int R)
  70. {
  71. if (L== || R==MAXY+ || R<L) return;
  72. int l=tree[now].l,r=tree[now].r;
  73. PushDown(now);
  74. if (L<=l && R>=r) {tree[now].tag=; tree[now].sum=; return;}
  75. int mid=(l+r)>>;
  76. if (L<=mid) IntervalChange(now<<,L,R);
  77. if (R>mid) IntervalChange(now<<|,L,R);
  78. Update(now);
  79. }
  80. inline int IntervalQuerySum(int now,int L,int R)
  81. {
  82. if (L== || R==MAXY+ || R<L) return ;
  83. int l=tree[now].l,r=tree[now].r;
  84. PushDown(now);
  85. if (L<=l && R>=r) return tree[now].sum;
  86. int mid=(l+r)>>,re=;
  87. if (L<=mid) re+=IntervalQuerySum(now<<,L,R);
  88. if (R>mid) re+=IntervalQuerySum(now<<|,L,R);
  89. return re;
  90. }
  91. inline int IntervalQueryBreak(int now,int L,int R)
  92. {
  93. if (L== || R==MAXY+ || R<L) return ;
  94. int l=tree[now].l,r=tree[now].r;
  95. PushDown(now);
  96. if (L<=l && R>=r) return tree[now].bk;
  97. int mid=(l+r)>>,re=MAXY;
  98. if (L<=mid) re=min(re,IntervalQueryBreak(now<<,L,R));
  99. if (R>mid) re=min(re,IntervalQueryBreak(now<<|,L,R));
  100. return re;
  101. }
  102. inline bool cmpLine(LineNode A,LineNode B) {return A.y!=B.y? A.y>B.y : A.x1<B.x1;}
  103. inline bool cmpCow(CowNode A,CowNode B) {return A.y>B.y;}
  104. inline bool cmpFlower(FlowerNode A,FlowerNode B) {return A.y>B.y;}
  105. int main()
  106. {
  107. F=read();
  108. for (int i=; i<=F; i++) fen[i].x1=read(),fen[i].y1=read(),fen[i].x2=read(),fen[i].y2=read();
  109. for (int i=; i<=F; i++)
  110. line[++tp]=(LineNode){fen[i].y1-,fen[i].x1,fen[i].x2,i,-},
  111. line[++tp]=(LineNode){fen[i].y2,fen[i].x1,fen[i].x2,i,};
  112. sort(line+,line+tp+,cmpLine);
  113. M=read();
  114. for (int i=; i<=M; i++) flo[i].x=read(),flo[i].y=read();
  115. sort(flo+,flo+M+,cmpFlower);
  116. N=read();
  117. for (int i=; i<=N; i++) cow[i].x=read(),cow[i].y=read(),cow[i].id=i;
  118. sort(cow+,cow+N+,cmpCow);
  119. BuildTree(,,MAXY);
  120. int nowl=,nowf=,nowc=,next,sum;
  121. for (int i=MAXY; i; i--)
  122. {
  123. while (line[nowl].y==i)
  124. {
  125. if (line[nowl].f==-)
  126. {
  127. IntervalChange(,line[nowl].x1,line[nowl].x2);
  128. PointChangeSum(,line[nowl].x1-,-tmp[line[nowl].id]);
  129. PointChangeBreak(,line[nowl].x1-,);
  130. PointChangeBreak(,line[nowl].x2,);
  131. }
  132. else
  133. {
  134. next=IntervalQueryBreak(,line[nowl].x2,MAXY);
  135. sum=IntervalQuerySum(,line[nowl].x1,line[nowl].x2);
  136. tmp[line[nowl].id]=IntervalQuerySum(,line[nowl].x2+,next);
  137. IntervalChange(,line[nowl].x1,line[nowl].x2);
  138. PointChangeSum(,line[nowl].x1-,sum+tmp[line[nowl].id]);
  139. PointChangeBreak(,line[nowl].x1-,);
  140. PointChangeBreak(,line[nowl].x2,);
  141. }
  142. nowl++;
  143. }
  144. while (flo[nowf].y==i)
  145. PointChangeSum(,flo[nowf].x,),nowf++;
  146. while (cow[nowc].y==i)
  147. next=IntervalQueryBreak(,cow[nowc].x,MAXY),
  148. ans[cow[nowc].id]=IntervalQuerySum(,cow[nowc].x,next),
  149. nowc++;
  150. }
  151. for (int i=; i<=N; i++) printf("%d\n",ans[i]);
  152. return ;
  153. }
  1. #include<cstdio>
  2. #include<iostream>
  3. using namespace std;
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. const int X=1e6+,Y=1e6,F=2e5+,M=2e5+,N=2e5+;
  8. char * cp=(char *)malloc();
  9. void in(int &x){
  10. while(*cp<''||*cp>'')++cp;
  11. for(x=;*cp>=''&&*cp<='';)x=x*+(*cp++^'');
  12. }
  13.  
  14. struct FenS{
  15. int xl,xr;
  16. int y;
  17. int i;
  18. bool flag;
  19. bool operator < (const FenS & o)const{
  20. return y!=o.y?y>o.y:xl<o.xl;
  21. }
  22. }fence[F<<];
  23. int fsum[F];
  24. struct FloS{
  25. int x,y;
  26. bool operator < (const FloS & o)const{
  27. return y>o.y;
  28. }
  29. }flower[M];
  30. struct CS{
  31. int x,y;
  32. int i;
  33. bool operator < (const CS & o)const{
  34. return y>o.y;
  35. }
  36. }cow[N];
  37. int ans[N];
  38.  
  39. struct SS{
  40. int cnt;
  41. bool cover;
  42. bool barrier;
  43. }segt[X<<];
  44. #define lson node<<1,l,l+r>>1
  45. #define rson node<<1|1,(l+r>>1)+1,r
  46. void out(int node,int l,int r){
  47. printf("segt[%d][%d,%d]={cnt=%d,cover=%d,barrier=%d}\n",node,l,r,segt[node].cnt,segt[node].cover,segt[node].barrier);
  48. }
  49. void pushup(int node){
  50. segt[node].cnt=segt[node<<].cnt+segt[node<<|].cnt;
  51. segt[node].barrier=segt[node<<].barrier|segt[node<<|].barrier;
  52. }
  53. void paint(int node){
  54. //printf("paint(%d)\n",node);
  55. segt[node].cover=;
  56. segt[node].cnt=;
  57. }
  58. void pushdown(int node){
  59. if(segt[node].cover){
  60. paint(node<<),paint(node<<|);
  61. segt[node].cover=;
  62. }
  63. }
  64. void add(int node,int l,int r,int x,int delta){
  65. //printf("add(%d,%d,%d,%d,%d)\n",node,l,r,x,delta);
  66. //out(node,l,r);
  67. segt[node].cnt+=delta;
  68. if(l!=r){
  69. pushdown(node);
  70. if(x<=l+r>>)add(lson,x,delta);
  71. else add(rson,x,delta);
  72. pushup(node);
  73. }
  74. //printf("add:");
  75. //out(node,l,r);
  76. }
  77. void cover(int node,int l,int r,int L,int R){
  78. //out(node,l,r);
  79. if(L<=l&&r<=R)paint(node);
  80. else{
  81. pushdown(node);
  82. if(L<=l+r>>)cover(lson,L,R);
  83. if(R>l+r>>)cover(rson,L,R);
  84. pushup(node);
  85. }
  86. }
  87. int query_cnt(int node,int l,int r,int L,int R){
  88. //printf("query(%d,%d,%d,%d,%d)\n",node,l,r,L,R);
  89. if(L<=l&&r<=R){
  90. //printf("query_cnt get [%d][%d,%d]=%d\n",node,l,r,segt[node].cnt);
  91. return segt[node].cnt;
  92. }
  93. else{
  94. pushdown(node);
  95. int ans=;
  96. if(L<=l+r>>)ans+=query_cnt(lson,L,R);
  97. if(R>l+r>>)ans+=query_cnt(rson,L,R);
  98. return ans;
  99. }
  100. }
  101. void update(int node,int l,int r,int x){
  102. if(l==r)segt[node].barrier^=;
  103. else{
  104. pushdown(node);
  105. if(x<=l+r>>)update(lson,x);
  106. else update(rson,x);
  107. pushup(node);
  108. }
  109. //printf("update:");
  110. //out(node,l,r);
  111. }
  112. int query_barrier(int node,int l,int r,int L){
  113. if(l>=L){
  114. //printf("Query_barrier Get ");
  115. //out(node,l,r);
  116. if(segt[node].barrier){
  117. while(l!=r)
  118. if(segt[node<<].barrier)node<<=,r=l+r>>;
  119. else node=node<<|,l=(l+r>>)+;
  120. return l;
  121. }
  122. else return ;
  123. }
  124. else{
  125. int tmp;
  126. pushdown(node);
  127. if(L<=l+r>>&&(tmp=query_barrier(lson,L)))return tmp;
  128. else return query_barrier(rson,L);
  129. }
  130. }
  131. int main(){
  132. freopen("cow.in","r",stdin);
  133. freopen("cow.out","w",stdout);
  134. fread(cp,,,stdin);
  135. int f;
  136. in(f);
  137. int x1,y1,x2,y2;
  138. for(int i=f;i--;){
  139. in(x1),in(y1),in(x2),in(y2);
  140. fence[i<<]=(FenS){x1,x2,y1-,i,};
  141. fence[i<<|]=(FenS){x1,x2,y2,i,};
  142. }
  143. sort(fence,fence+(f<<));
  144. int m;
  145. in(m);
  146. for(int i=m;i--;)in(flower[i].x),in(flower[i].y);
  147. sort(flower,flower+m);
  148. int n;
  149. in(n);
  150. for(int i=;i<n;++i){
  151. in(cow[i].x),in(cow[i].y);
  152. cow[i].i=i;
  153. }
  154. sort(cow,cow+n);
  155.  
  156. f=m=n=;
  157. update(,,Y,Y);
  158. int sum,br;
  159. for(int i=Y;i;--i){
  160. //printf("----%d----\n",i);
  161. for(;fence[f].y==i;++f)
  162. if(fence[f].flag==){
  163. cover(,,Y,fence[f].xl,fence[f].xr);
  164. if(fence[f].xl!=)add(,,Y,fence[f].xl-,-fsum[fence[f].i]);
  165.  
  166. if(fence[f].xl!=)update(,,Y,fence[f].xl-);
  167. if(fence[f].xr!=Y)update(,,Y,fence[f].xr);
  168. }
  169. else{
  170. br=query_barrier(,,Y,fence[f].xr);
  171. sum=query_cnt(,,Y,fence[f].xl,fence[f].xr);
  172. fsum[fence[f].i]=query_cnt(,,Y,fence[f].xr+,br);
  173. cover(,,Y,fence[f].xl,fence[f].xr);
  174. if(fence[f].xl>)add(,,Y,fence[f].xl-,sum+fsum[fence[f].i]);
  175.  
  176. if(fence[f].xl!=)update(,,Y,fence[f].xl-);
  177. if(fence[f].xr!=Y)update(,,Y,fence[f].xr);
  178. }
  179. for(;flower[m].y==i;++m){
  180. //cout<<flower[m].x<<","<<flower[m].y<<endl;
  181. add(,,Y,flower[m].x,);
  182. }
  183. for(;cow[n].y==i;++n){
  184. br=query_barrier(,,Y,cow[n].x);
  185. //printf("br(%d)=%d\n",cow[n].x,br);
  186. ans[cow[n].i]=query_cnt(,,Y,cow[n].x,br);
  187. //printf("query(%d,%d)=%d\n",cow[n].x,br,ans[cow[n].i]);
  188. }
  189. }
  190.  
  191. for(int i=;i<n;++i)printf("%d\n",ans[i]);
  192. }

TA爷的代码

TA爷的模拟赛.....暴力都没写.....有点对不起TA爷....(不过似乎当时这题没得分的?)

自己的代码比较丑,这里附上当时TA爷的std,供参考

【BZOJ-4422】Cow Confinement 线段树 + 扫描线 + 差分 (优化DP)的更多相关文章

  1. BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4422 我真服了..这题我能调一天半,最后还是对拍拍出来的...脑子还是有病啊 题解: ...

  2. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  3. 线段树区间合并优化dp——cf1197E(好)

    线段树优化dp的常见套路题,就是先按某个参数排序,然后按这个下标建立线段树,再去优化dp 本题由于要维护两个数据:最小值和对应的方案数,所以用线段树区间合并 /* dp[i]表示第i个套娃作为最内层的 ...

  4. bzoj 2131 : 免费的馅饼 (树状数组优化dp)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2131 思路: 题目给出了每个馅饼的下落时间t,和位置p,以及价值v,我们可以得到如下状态 ...

  5. [BZOJ 4771]七彩树(可持久化线段树+树上差分)

    [BZOJ 4771]七彩树(可持久化线段树+树上差分) 题面 给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节点的颜色为c[i].如果c[i] ...

  6. BZOJ 1818 线段树+扫描线

    思路: 可以把题目转化成 给你一些沿坐标轴方向的线段 让你求交点个数 然后就线段树+扫描线 搞一搞 (线段不包含断点 最后+n 这种方式 比线段包含断点+各种特判要好写得多) //By SiriusR ...

  7. Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)

    题目链接:http://codeforces.com/contest/522/problem/D 题目大意:  给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...

  8. 【POJ-2482】Stars in your window 线段树 + 扫描线

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11706   Accepted:  ...

  9. HDU 4419 Colourful Rectangle --离散化+线段树扫描线

    题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...

随机推荐

  1. PHP & Delphi 語法

    明 C(区分大小写) Delphi(不区分大小写) PHP(区分大小写) 整型变量的定义 1 2 3 4 5 6 7 char a = 'a';         /* 8位有符号*/ int a=10 ...

  2. Java核心技术点之反射

    1. 概述 Java 反射是可以让我们在运行时获取类的方法.属性.父类.接口等类的内部信息的机制.也就是说,反射本质上是一个“反着来”的过程.我们通过new创建一个类的实例时,实际上是由Java虚拟机 ...

  3. BZOJ 1834 【ZJOI2010】 network 网络扩容

    Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. 将1到N的最大流增加K所需的 ...

  4. WF4.0 工作流设计器 传入参数问题记录?

    在本公司的流程设计器 ,如果流程中使用了传入参数,应先定义 参数,然后再拖动节点,才能正确提交,否则出错,原因未查明,只观察到现象.

  5. android中按电源键锁屏然后解锁导致Activity调用onDestory以及如何防止锁屏

    今天在android项目中按电源键锁屏,然后解锁,发现子Activity关闭了,回到了主页,这个问题困扰了我很久,最后打log发现,在按电源键的时候,调用了子Activity的onDestroy()方 ...

  6. 异常检测算法--Isolation Forest

    南大周志华老师在2010年提出一个异常检测算法Isolation Forest,在工业界很实用,算法效果好,时间效率高,能有效处理高维数据和海量数据,这里对这个算法进行简要总结. iTree 提到森林 ...

  7. PHP 基础笔记

    数据类型 字符串 整数 浮点数 布尔值 数组 对象 NULL 未定义的变量,数据类型为 NULL. PHP 中数组和对象是不同的类型,而 js 中数组即为对象.(ps: es6 已经内置了 class ...

  8. [【codechefCHSEQ22】Chef and Favourite Sequence(并查集)

    题目:http://hzwer.com/3419.html 题意:给你一个全是0的数列,有m种操作[Li,Ri],每次操作就将下标处于[Li,Ri]的元素取反.你可以选若干个操作来使这个数列最后变成别 ...

  9. C程序中对时间的处理——time库函数详解

    包含文件:<sys/time.h> <time.h> 一.在C语言中有time_t, tm, timeval等几种类型的时间 1.time_t time_t实际上是长整数类型, ...

  10. HFS汉化版|简易HTTP服务器

    专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,只要解压缩后执 ...