CDOJ 1071 秋实大哥下棋
2016-03-28 21:32
239 查看
秋实大哥下棋
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 3 1 1 3 2 2 3 2 3 2 3 2 1 3 3 1 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 ex freopen ("in.txt","r",stdin); #endif int 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 ex1 if (x_solve(m,sz_x) && y_solve(n,sz_y)) { printf("YES\n"); } else { printf("NO\n"); } #endif x_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"); } } }
相关文章推荐
- hdu 5651 xiaoxin juju needs help 逆元 两种求解方式
- 本月有几天
- uestc1134男神的约会【状压dp】
- File 类
- [置顶] 未知图片宽高水平垂直居中
- D17
- iOS文件操作学习3-28
- 求四个数的最大公约数
- ehcache memcache redis三大缓存男高音
- AndroidStudio项目提交(更新)到github最详细步骤
- 第五周项目1 三角形类练习(4)
- Collections工具类下的sort方法
- dfs
- 排序算法之归并排序(Java)
- 【java web】--Jsp与beetl的前世今缘
- 求两个数的最大公约数
- 排序算法之快速排序(Java)
- JAVA继承特点的小总结
- AQTime教程
- 对关于iOS图片压缩的一点积累