您的位置:首页 > 其它

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");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: