【cdoj 1071】秋实大哥下棋 扫描线+线段树+脑洞

来源:互联网 发布:清新博客程序源码 编辑:程序博客网 时间:2024/05/17 07:32

首先,我们注意到就是题目中所说的,只有在矩形内部的车才能够保护矩形内部的各个点,这就说明,我们需要在进入矩阵和离开矩阵的时候要分别判断,而这就是一个相当大的扫描线的提示。

先分析一边的情况,我们以x坐标从左到右开始扫,如果一个矩形能够被车保护,那么他的右边到左边之间的所有车能够把这个矩阵的上边到下边之间的纵坐标全部覆盖完,也就是说现在需要处理两个东西,一个是是否覆盖完,一个是覆盖完所用的车中的最小横纵标(如果连最小横坐标都大于它的左边,那么所用的车一定在左右边之间),而这些东西都可以用一颗线段树全部解决,线段树直接维护扫描线上的最小横坐标,如果没有覆盖,最小横坐标小于矩阵左边横坐标


那么也有可能是上下啊,没关系,把所有横纵坐标swap一次,再原封不动的做一次就过了。

注意,swap后重新排序,一开始我忘了wa了一次还是第一组

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define maxn 100006*2#define ls u<<1,l,mid#define rs u<<1|1,mid+1,rusing namespace std;int n,m,k,q,vis[maxn],cnt,mx,my;struct CAR{int x,y;bool operator <(const CAR& b)const{return x==b.x?y>b.y:x<b.x;}}car[maxn];struct edge{int rx,ry,id,lx,ly;bool operator<(const edge& b)const{return rx==b.rx?ry>b.ry:rx<b.rx;}}e[maxn];struct node{int l,r,Min;}nod[100005*4];void push_up(int u){nod[u].Min=min(nod[u<<1].Min,nod[u<<1|1].Min);}void build(int u,int l,int r){nod[u].l=l,nod[u].r=r;if(l==r){nod[u].Min=-1;return;}int mid=l+r>>1;build(ls);build(rs);push_up(u);}void updata(int u,int l,int r,int x,int add){if(l==r){nod[u].Min=add;return ;}int mid=l+r>>1;if(x>mid)updata(rs,x,add);else updata(ls,x,add);push_up(u);}int query(int u,int l,int r,int x,int y){if(x==l&&r==y)return nod[u].Min;int mid=l+r>>1;if(x>mid)return query(rs,x,y);else if(y<=mid)return query(ls,x,y);else return min(query(ls,x,mid),query(rs,mid+1,y));}void find(){int pre=1;build(1,1,mx);for(int i=1;i<=q;i++){while(car[pre].x<=e[i].rx&&pre<=k){updata(1,1,mx,car[pre].y,car[pre].x);pre++;}int Min=query(1,1,mx,e[i].ly,e[i].ry);if(Min>=e[i].lx)vis[e[i].id]=1;}}int main(){scanf("%d%d%d%d",&n,&m,&k,&q);for(int i=1;i<=k;i++){scanf("%d%d",&car[i].x,&car[i].y);mx=max(max(mx,car[i].x),car[i].y);}for(int i=1;i<=q;i++){scanf("%d%d%d%d",&e[i].lx,&e[i].ly,&e[i].rx,&e[i].ry);mx=max(mx,max(e[i].lx,e[i].ly));mx=max(mx,max(e[i].rx,e[i].ry));e[i].id=i;}mx=100000;sort(car+1,car+1+k);sort(e+1,e+1+q);find();for(int i=1;i<=k;i++)swap(car[i].x,car[i].y);for(int i=1;i<=q;i++)swap(e[i].lx,e[i].ly),swap(e[i].rx,e[i].ry);sort(car+1,car+1+k);sort(e+1,e+1+q);find();for(int i=1;i<=q;i++){if(vis[i])printf("YES\n");else printf("NO\n");}return 0;}


0 0
原创粉丝点击