51NOD 1559:车和矩形——题解
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1559
波雷卡普有一个n×m,大小的棋盘,上面有k个车。他又放了q个矩形在上面。每一个矩形要受到保护。矩形受到保护的意思是对于该矩形内部所有的格子能够被这个矩形内的某个车攻击到或者被占据,和矩形外面的车无关,即矩形外面的车不能攻击到矩形里面。车的位置是固定的。
样例解释:
对于最后一个矩形,用红色框框表示的,因为(1,2)不能被某个车攻击到,所以是NO。
题其实不难,但是没有一定的套路基础不好想(你看我这么纯洁也没啥套路啊……)
参考:https://blog.csdn.net/Bahuia/article/details/69555088
一眼看是一个线段树,但是只能维护矩形里面的车所以考虑扫描线。
再思考什么情况下矩形是YES的:每行有车或每列有车。
于是我们只需要做两遍,第二遍把横纵坐标都反过来再做一遍就行了,只要有一个YES就是YES。
那么思路有了,我们要怎么做?
将矩形看做区间查询[x1,x2],将车看做单点修改x2为y2,这样我们将车也看成矩形,对所有矩形y2进行排序,然后按照顺序加,线段树维护区间y坐标最小值。
这样我们区间查询的答案如果>=y1那么就是YES,否则就是NO。
#include<map> #include<cmath> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<vector> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=4e5+5; const int INF=1e9; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct line{ int x1,y1,x2,y2,w,id; }d[N]; int n,m,k,q,tr[N]; bool ans[N]; inline bool cmp(line a,line b){ return a.y2==b.y2?a.w<b.w:a.y2<b.y2; } void build(int a,int l,int r){ tr[a]=0; if(l==r)return; int mid=(l+r)>>1; build(a<<1,l,mid);build(a<<1|1,mid+1,r); } void mdy(int a,int l,int r,int x,int y){ if(l==r){ tr[a]=y;return; } int mid=(l+r)>>1; if(x<=mid)mdy(a<<1,l,mid,x,y); else mdy(a<<1|1,mid+1,r,x,y); tr[a]=min(tr[a<<1],tr[a<<1|1]); } int qry(int a,int l,int r,int l1,int r1){ if(r<l1||r1<l)return INF; if(l1<=l&&r<=r1)return tr[a]; int mid=(l+r)>>1; return min(qry(a<<1,l,mid,l1,r1),qry(a<<1|1,mid+1,r,l1,r1)); } void solve(){ sort(d+1,d+q+1,cmp); build(1,1,n); for(int i=1;i<=q;i++){ if(!d[i].w){ mdy(1,1,n,d[i].x2,d[i].y2); }else if(!ans[d[i].id]){ ans[d[i].id]=qry(1,1,n,d[i].x1,d[i].x2)>=d[i].y1; } } } int main(){ n=read(),m=read(),k=read(),q=read(); for(int i=1;i<=k;i++){ d[i].x2=read();d[i].y2=read(); d[i].w=0; } for(int i=1;i<=q;i++){ d[i+k].x1=read();d[i+k].y1=read(); d[i+k].x2=read();d[i+k].y2=read(); d[i+k].id=i;d[i+k].w=1; } q+=k;solve(); swap(n,m); for(int i=1;i<=q;i++){ swap(d[i].x1,d[i].y1); swap(d[i].x2,d[i].y2); } solve(); for(int i=1;i<=q-k;i++) if(ans[i])puts("YES"); else puts("NO"); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +
+++++++++++++++++++++++++++++++++++++++++++