2 2 2 1 2 1 1 1 1 1 2 2 1 2 2 2 2 2 1 1 1 1 2 2 1 2 2
Yes No YesHintHuge input, scanf recommended.
/************************************************************************/
附上该题对应的中文题
在一个n×m的国际象棋棋盘上有很多车(Rook),其中车可以攻击他所属的一行或一列,包括它自己所在的位置。
现在还有很多询问,每次询问给定一个棋盘内部的矩形,问矩形内部的所有格子是否都被车攻击到?
输入文件包含多组数据,第一行为数据组数T。 每组数据有4个正整数n,m,K,Q。 K为车的数量,Q为询问的个数。 接下来有K行,每行两个整数x,y , 表示车所在的坐标。 再接下来有Q行,每行4个整数x1,y1,x2,y2,表示询问的矩形的左下角与右上角的坐标。 1≤n,m,K,Q≤100,000. 1≤x≤n,1≤y≤m. 1≤x1≤x2≤n,1≤y1≤y2≤m.
对于每组询问,输出Yes或No。
2 2 2 1 2 1 1 1 1 1 2 2 1 2 2 2 2 2 1 1 1 1 2 2 1 2 2
Yes No Yes
输入数据过大,建议使用scanf
出题人的解题思路:
可以发现如果一个矩阵被全部攻击到,很显然要么是因为它的每一行都有车,或者每一列都有车。
所以只需要记录一下哪些行和哪些列有车,对于每个询问只需要做一个前缀和就可以知道答案了。
表示默默地将有车的行和列分别标记为0,没有的记为1,然后维护行线段树与列线段树,求区间最值,有1就是1,也就是说车到不了的位置是1#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<stdlib.h> #include<cmath> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 100005; const int inf = 1000000000; const int mod = 2009; int a[N],b[N]; struct node { int l,r,ma; }tree[N*4],point[N*4]; void build(int l,int r,int p) { tree[p].l = l; tree[p].r = r; tree[p].ma = -1; if(l == r) { tree[p].ma = a[l]; return; } int mid = (l+r)/2; build(l,mid,p*2); build(mid+1,r,p*2+1); tree[p].ma = max(tree[p*2].ma,tree[p*2+1].ma); } int query(int x,int y,int p) { if(x == tree[p].l && y == tree[p].r) return tree[p].ma; int mid = (tree[p].l + tree[p].r)/2; if(x > mid) return query(x,y,p*2+1); else if(y <= mid) return query(x,y,p*2); else return max(query(x,mid,p*2),query(mid+1,y,p*2+1)); } void build1(int l,int r,int p) { point[p].l = l; point[p].r = r; point[p].ma = -1; if(l == r) { point[p].ma = b[l]; return; } int mid = (l+r)/2; build1(l,mid,p*2); build1(mid+1,r,p*2+1); point[p].ma = max(point[p*2].ma,point[p*2+1].ma); } int query1(int x,int y,int p) { if(x == point[p].l && y == point[p].r) return point[p].ma; int mid = (point[p].l + point[p].r)/2; if(x > mid) return query1(x,y,p*2+1); else if(y <= mid) return query1(x,y,p*2); else return max(query1(x,mid,p*2),query1(mid+1,y,p*2+1)); } int main() { int T,i,j,k,n,m,K,Q,q,x,y,x1,y1,x2,y2; scanf("%d",&T); while(T--) { scanf("%d%d%d%d",&n,&m,&K,&Q); for(i=1;i<=n;i++) a[i]=1; for(i=1;i<=m;i++) b[i]=1; for(i=0;i<K;i++) { scanf("%d%d",&x,&y); a[x]=0,b[y]=0; } /*for(i=1;i<=n;i++) printf("%d ",a[i]); puts("#"); for(i=1;i<=m;i++) printf("%d ",b[i]); puts("@");*/ build(1,n,1); build1(1,m,1); for(i=1;i<=Q;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); //printf("%d %d\n",query(x1,x2,1),query1(y1,y2,1)); if(!query(x1,x2,1)||!query1(y1,y2,1)) puts("Yes"); else puts("No"); } } return 0; }菜鸟成长记