CDOJ 1071 秋实大哥下棋

来源:互联网 发布:能听着背单词的软件 编辑:程序博客网 时间:2024/06/10 09:43

秋实大哥下棋

limit 1s 65535KB

胜负胸中料已明,又从堂上出奇兵。秋实大哥是一个下棋好手,独孤求败的他觉得下棋已经无法满足他了,他开始研究一种新的玩法。
在一个n×m的棋盘上,放置了k个车,并且他在棋盘上标出了q个矩形,表示矩形内部是战略要地。秋实大哥要求一个矩形内的每一个格子,都至少能被一辆在矩形内的车攻击到,那么这个矩形就是被完整保护的。
现在秋实大哥想知道每一个矩形是否被完整保护。


input

第一行包含四个整数n,m,k,q,表示棋盘的大小,车的数量以及矩形的数量。
接来下k行,每行包含两个整数x,y,表示有一辆车位于从左往右第x列,从下往上第y行。
接下来q行,每行包含四个整数x1,y1,x2,y2,表示一个矩形的左下角和右上角坐标。
1≤n,m≤105,1≤k,q≤2⋅105,1≤x1≤x2≤105,1≤y1≤y2≤105,1≤x≤105,1≤y≤105。

output

输出q行,对于每一次询问,这个矩形若被完整保护了输出"YES",否则输出"NO"。

sameple input

4 3 3 31 13 22 32 3 2 32 1 3 31 2 2 3
sameple output

YES
YES
NO


题解

好难啊,完全不会

所以看题解,问大神,折腾了好久终于敢自己写一发了……

竟然一发过,开心……


但是题解很不好表述啊,怎么说,X,Y分开进行,比如X轴方向扫描,在Y轴上建线段树,线段树维护[y1,y2]区间内车的X的最小值。

每次扫描到一个矩形的右边,就询问[y1,y2]区间中车的X的最小值,如果X小于该矩形的左边,说明纵坐标在[Y1,Y2]区间的车至少一辆不在矩形内,覆盖失败

Y轴一样

#include<bits/stdc++.h>#include<vector>using namespace std;const int maxn=1e5;const int max_size=1<<18;const int inf=1e7;struct Carriage{int x;int y;};Carriage car[2*maxn+5];struct Retangular{int x1,x2,y1,y2;};Retangular ret[2*maxn+5];vector <int> x_car[maxn+5];vector <int> y_car[maxn+5];vector <int> rside[maxn+5];vector <int> hside[maxn+5];int x_tree[max_size+5];int y_tree[max_size+5];int ans[2*maxn+5];void update(int tree[],int x,int m,int sz){x+=sz-1;tree[x]=m;x>>=1;while (x>=1){tree[x]=min(tree[x<<1],tree[(x<<1)+1]);x>>=1;}}int query(int tree[],int a,int b,int k,int l,int r){if (a<=l && r<=b) return tree[k];else if (r<a || b<l) return inf;else{int mid=(l+r)/2;return min(query(tree,a,b,k<<1,l,mid),query(tree,a,b,(k<<1)+1,mid+1,r));}}void y_solve(int n,int sz_y){for (int i=1;i<=n;++i){if (!x_car[i].empty()){for (int j=0;j<x_car[i].size();++j){int t=x_car[i][j];update(y_tree,car[t].y,car[t].x,sz_y);}}if (!rside[i].empty()){for (int j=0;j<rside[i].size();++j){int t=rside[i][j];if (query(y_tree,ret[t].y1,ret[t].y2,1,1,sz_y)<ret[t].x1) {ans[t]+=1;}}}}}void x_solve(int m,int sz_x){for (int i=1;i<=m;++i){if (!y_car[i].empty()){for (int j=0;j<y_car[i].size();++j){int t=y_car[i][j];update(x_tree,car[t].x,car[t].y,sz_x);}}if (!hside[i].empty()){for (int j=0;j<hside[i].size();++j){int t=hside[i][j];if (query(x_tree,ret[t].x1,ret[t].x2,1,1,sz_x)<ret[t].y1) {ans[t]+=1;}}}}} int main(void){#ifdef exfreopen ("in.txt","r",stdin);#endifint n,m,k,q;int x,y,x1,x2,y1,y2;scanf("%d%d%d%d",&n,&m,&k,&q);int sz_x=1;while (sz_x<n) sz_x<<=1;int sz_y=1;while (sz_y<m) sz_y<<=1;for (int i=1;i<=k;++i){scanf("%d%d",&x,&y);car[i].x=x;car[i].y=y;x_car[x].push_back(i);y_car[y].push_back(i);}for (int i=1;i<=q;++i){scanf("%d%d%d%d",&x1,&y1,&x2,&y2);ret[i].x1=x1;ret[i].x2=x2;ret[i].y1=y1;ret[i].y2=y2;rside[x2].push_back(i);hside[y2].push_back(i);}#ifdef ex1if (x_solve(m,sz_x) && y_solve(n,sz_y)){printf("YES\n");}else{printf("NO\n");}#endifx_solve(m,sz_x);y_solve(n,sz_y);for (int i=1;i<=q;++i){if (ans[i]==2) printf("NO\n");else{printf("YES\n");}}}


0 0
原创粉丝点击