以下内容来自ShallWe's Blog

题目

题目链接

4422: [Cerc2015]Cow Confinement

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个花。

解题报告

考试的时候连暴力都没有打出来,真是十分的失败。
介绍一点部分分的做法:

  1. 如果\(x,y\)比较小的话,那么很显然可以直接暴力dfs
  2. 如果\(n\)比较小的话,可以离散化,然后暴力$O \left( n^3 \right) $
  3. 同样如果要做到\(O \left( n^2 \right)\) ,就需要dp,也就是令\(f[i][j]=f[i][j+1]+f[i+1][j]-f[i+1][j+1]\) ,简单易懂。

考虑优化上述dp,离线+线段树,有这样一个事情, 就是cows只能向下或者向右走,这样对于一个点\((x,y)\),他可能拥有\((x+1,y)\) \((x,y+1)\)无法到达的一些flowers,用类似于差分的想法, 令\(f[i]\)表示当前行\(f[i+1]\)无法到达的花朵,实际上cow\((x,y)\)的答案就是找到下方第一个栅栏(实际上是横向的一条边)\((x_b , y)\),查询当前列\(y\)一个差分的和\((x,x_b)\bf\)

问题更加单纯了,就是转移,详细一点说就是从\(y+1\)到\(y\),差分信息怎样变化

  1. 没有栅栏只有花?只需要单点修改下就好

  2. 出现一个栅栏? ,也就是进入栅栏的边界,设\((x_l ,x_r)\)是栅栏的上下坐标,很显然,\((x_l,x_r)\)部分的差分应该删掉,并且标记为被覆盖,而\(x_l-1\)这个位置,会获得\((x_l,x_r)\)部分的差分,这点很容易,难以想到的一点是,此时需要询问一下\(cow(x_r+1,y+1)\),并记录这个数值,为3做准备。

    这个首先也需要做一个区间归零,然后要在\((x_l-1,y)\)的位置减去这个区间加入时做的询问,原因是没有了栅栏的限制,下方的差分会计算两次。这个我感受了好久。

程序的实现

单点修改,区间覆盖(归零),区间查询,从某位置开始第一个障碍点的添加和查询
好难的样子,但好像一个线段树就艹掉了。

代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int X=1000001,Y=1000000,N=2000001;
struct FEN{int xl,xr,y,i;bool flag;bool operator < (const FEN &o)const{return y!=o.y?y>o.y:xl<o.xl;}
} fen[N<<1];struct FLO{int x,y;bool operator < (const FLO &o)const{return y>o.y;}
} flo[N];
struct CS{int x,y,i;bool operator < (const CS &o)const{return y>o.y;}
} cow[N];
struct SS{int nm;bool cover,cut;
} seg[X<<2];
int ans[N],fs[N];;
char * cp=(char *)malloc(20000000);
inline void in(int &x){for (;*cp<'0'||*cp>'9';cp++);for (x=0;*cp>='0'&&*cp<='9';cp++)x=x*10+*cp-'0';
}
inline void pushup(int x){seg[x].nm=seg[x<<1].nm+seg[x<<1|1].nm;seg[x].cut=seg[x<<1].cut|seg[x<<1|1].cut;
}
inline void paint(int x){seg[x].cover=1;seg[x].nm=0;
}
inline void pushdown(int x){if(seg[x].cover){paint(x<<1),paint(x<<1|1);seg[x].cover=0;}
}
void add(int x,int l,int r,int pur,int val){seg[x].nm+=val;if (l==r) return; int mid=(l+r)>>1;pushdown(x);if(pur<=mid)add(x<<1,l,mid,pur,val);else add(x<<1|1,mid+1,r,pur,val);pushup(x);
}
void cover(int x,int l,int r,int L,int R){if(L<=l&&r<=R){paint(x);return;}pushdown(x);int mid=(l+r)>>1;if(L<=mid)cover(x<<1,l,mid,L,R);if(R>mid)cover(x<<1|1,mid+1,r,L,R);pushup(x);
}
int query(int x,int l,int r,int L,int R){if(L<=l&&r<=R){return seg[x].nm;}int mid=(l+r)>>1,ans=0;pushdown(x);if(L<=mid)ans+=query(x<<1,l,mid,L,R);if(R>mid)ans+=query(x<<1|1,mid+1,r,L,R);return ans;
}
void update(int x,int l,int r,int pur){if(l==r){seg[x].cut^=1;return; }int mid=l+r>>1;pushdown(x);if(pur<=mid)update(x<<1,l,mid,pur);else update(x<<1|1,mid+1,r,pur);pushup(x);
}
int next(int x,int l,int r,int L){if(l>=L){if(seg[x].cut){while(l!=r)if(seg[x<<1].cut)x<<=1,r=l+r>>1;else x=x<<1|1,l=(l+r>>1)+1;return l;}else return 0;}int tmp,mid=(l+r)>>1;pushdown(x);if(L<=mid&&(tmp=next(x<<1,l,mid,L)))return tmp;else return next(x<<1|1,mid+1,r,L);
}
int main(){
//  freopen("4422.in","r",stdin);fread(cp,1,20000000,stdin);int f,m,n,x1,y1,x2,y2;in(f);for(int i=f;i--;){in(x1),in(y1),in(x2),in(y2);fen[i<<1]=(FEN){x1,x2,y1-1,i,0};fen[i<<1|1]=(FEN){x1,x2,y2,i,1};}sort(fen,fen+(f<<1));in(m);for(int i=m;i--;)in(flo[i].x),in(flo[i].y);sort(flo,flo+m);in(n);for(int i=0;i<n;++i){in(cow[i].x),in(cow[i].y);cow[i].i=i;}sort(cow,cow+n);f=m=n=0;update(1,1,Y,Y);int sum,cut;for(int i=Y;i;--i){for(;fen[f].y==i;++f)if(fen[f].flag==0){cover(1,1,Y,fen[f].xl,fen[f].xr);if(fen[f].xl!=1)add(1,1,Y,fen[f].xl-1,-fs[fen[f].i]);if(fen[f].xl!=1)update(1,1,Y,fen[f].xl-1);if(fen[f].xr!=Y)update(1,1,Y,fen[f].xr);}else{cut=next(1,1,Y,fen[f].xr);sum=query(1,1,Y,fen[f].xl,fen[f].xr);fs[fen[f].i]=query(1,1,Y,fen[f].xr+1,cut);cover(1,1,Y,fen[f].xl,fen[f].xr);if(fen[f].xl>1)add(1,1,Y,fen[f].xl-1,sum+fs[fen[f].i]);if(fen[f].xl!=1)update(1,1,Y,fen[f].xl-1);if(fen[f].xr!=Y)update(1,1,Y,fen[f].xr);}for(;flo[m].y==i;++m){add(1,1,Y,flo[m].x,1);}for(;cow[n].y==i;++n){cut=next(1,1,Y,cow[n].x);ans[cow[n].i]=query(1,1,Y,cow[n].x,cut);}}for(int i=0;i<n;++i)printf("%d\n",ans[i]);return 0;
}

转载于:https://www.cnblogs.com/ShallWe2000/p/5762193.html

Bzoj 4422: [Cerc2015]Cow Confinement(线段树+扫描线)相关推荐

  1. 【BZOJ-4422】Cow Confinement 线段树 + 扫描线 + 差分 (优化DP)

    4422: [Cerc2015]Cow Confinement Time Limit: 50 Sec  Memory Limit: 512 MB Submit: 61  Solved: 26 [Sub ...

  2. [扫描线 线段树] BZOJ 4422 [Cerc2015]Cow Confinement

    好题 从右往左扫 我们在线段树上维护 fyf_y ff的含义 如果下方是栅栏 那么fyf_y就是(x,y)(x,y)的答案 否则 fyf_y 是 (x,y)(x,y) 比 (x,y+1)(x,y+1) ...

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

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

  4. bzoj 1645: [Usaco2007 Open]City Horizon 城市地平线(线段树扫描线)

    1645: [Usaco2007 Open]City Horizon 城市地平线 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 732  Solved: ...

  5. 线段树扫描线求矩形周长详解

    线段树扫描线求矩形周长详解 原创 wucstdio 最后发布于2018-04-24 16:12:09 阅读数 841 收藏 发布于2018-04-24 16:12:09 版权声明:本文为博主原创文章, ...

  6. hdu3255 线段树扫描线求体积

    题意:       给你n个矩形,每个矩形上都有一个权值(该矩形单位面积的价值),矩形之间可能重叠,重叠部分的权值按照最大的算,最后问这n个矩形组成的图形的最大价值. 思路:       线段树扫描线 ...

  7. hdu1542 线段树扫描线求矩形面积的并

    题意:       给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路:       自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...

  8. hdu 1542 Atlantis (线段树+扫描线)

    http://acm.hdu.edu.cn/showproblem.php?pid=1542 单纯的线段树+扫描线求面积并,需要离散化. code: #include <cstdlib> ...

  9. HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

    版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...

最新文章

  1. oss对象存储服务操作
  2. 学习笔记 --- 编码过程中常见的三种异步方式
  3. 【习题 7-2 UVA-225】Golygons
  4. Vue项目webpack打包部署到Tomcat,刷新报404错
  5. 线程(一)__同步以及死锁
  6. 从零基础入门Tensorflow2.0 ----五、22TF1.0计算图构建
  7. java byte 相等比较_Java字节码跟真正汇编的比较
  8. 关于NX UG11.0在visual studio中不能创建模板的问题
  9. 小白学Oracle基础知识(一)
  10. html 播放ogg,HTML5中video 和 ogg
  11. 腾讯入股艺龙,在线旅游市场引发关注
  12. 模拟数字接口及调制解调器
  13. NGS数据分析实践:06. 数据预处理 - 序列比对+PCR重复标记+Indel区域重比对+碱基质量重校正
  14. python获取涨停股票_摸索:半天完成Python获取数据,建立每日涨停股票池。
  15. Python毕业设计必备案例:【学生信息管理系统】
  16. 荣耀十支持鸿蒙OS,不是所有华为荣耀手机都能升级华为鸿蒙OS,只有这48款才行...
  17. 【Homebrew】Homebrew 介绍与安装
  18. docker部署flask应用
  19. 新手必备pr 2021快速入门教程「十」PR基础视频调色
  20. 研究生初试录取系统C语言,研究生初试录取管理系统

热门文章

  1. * poj 3159 Candies 最短路 dijkstra堆优化
  2. python rename dataframe,python rename dataframe_python – 重命名Pandas DataFra
  3. 2020年日历电子版(打印版)_2020年日历电子版(打印版)79451
  4. python二进制整数的定义_TensorFlow定义操作整数的二进制表示
  5. navicate将远程数据库导入到本地数据库
  6. java t9 字母组合_太赞了!美团T9终于整理出Java架构之完美设计实战开源文档
  7. html等待图片全部加载,imgLoad等待图片资源加载完成后执行函数(图片预加载)...
  8. windows进入mysql改user_mysql:Windows修改MySQL数据库密码(修改或忘记密码)
  9. python不同时间周期k线_请问期货不同时间级别的k线呈现相反形态怎么判断买卖点?...
  10. html页面css代码写在哪里,HTML、CSS代码书写规范