H-Hopping Rabbit
题目
链接:
https://ac.nowcoder.com/acm/contest/11257/H
来源:牛客网
题目大意:
一只兔子在草原上跳来跳去,草原上有猎人布下的n个陷阱.现在将草原看作一个二维直角坐标系,兔子看作一个点,陷阱看作一个矩阵(且它的边必定与x轴或y轴平行),兔子每次会沿x轴或y轴方向移动距离d(即如果兔子在(x,y),它跳一次后在(x+d,y),
(x-d,y),(x,y+d),(x,y-d)四个点中的一个.问在坐标系中是否存在一个点(x0+0.5,y0+0.5),使兔子无论怎么跳都不会掉进陷阱.如果存在,第一行输出"YES",第二行输出任意一个满足条件的x0和y0,中间用k空格隔开.否则输出"NO".
思路
首先,我们可以想象得出来,如果一组数据有解,那么一定有解在由(0,0),(0,d-1),
(d-1,d-1),(d-1,0)这4个点依次连接所形成的矩形里(因为我们可以将矩形平移,每次平移d个单位,平移后矩形内部的点是不符合题意的).所以我们先将所有矩形移至第一象限,这样便于计算,但是有的矩形会很大,平移后超出了这个范围(如下图).
这时我们就要将矩形再次平移,将它向下,向左,同时向下和向左d个单位,并把平移后在红色范围内的部分留下.然后用扫描线+线段树来对矩形进行下一步的操作.具体见代码.
代码实现
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N=100010;
int n,d,l1,r1,xx;
bool flag=0;
struct tree{
int len,cnt;
}a[N*4];
struct xian{
int tl,tr;//左右边坐标
int x;
};
vector<xian> x[N];
void pushup(int l,int r,int rt){
if(a[rt].cnt)
a[rt].len=r-l+1;
else if(l==r)
a[rt].len=0;
else
a[rt].len=a[rt*2].len+a[rt*2+1].len;
}
void add(int x1,int y1,int x2,int y2){//将扫描线加入动态数组中
x[x1].push_back((xian){y1,y2,1});
x[x2+1].push_back((xian){y1,y2,-1});
}
void md(int &x){
x%=d;
if(x<0) x+=d;
}
void change(int l,int r,int rt){//离散化
if(l1<=l&&r<=r1){
a[rt].cnt+=xx;
pushup(l,r,rt);
return;
}
int mid=(l+r)/2;
if(l1<=mid) change(l,mid,2*rt);
if(mid<r1) change(mid+1,r,2*rt+1);
pushup(l,r,rt);
}
void get(int l,int r,int rt){
if(a[rt].len==0){
printf("%d\n",l);
return;
}
int mid=(l+r)/2;
if(a[2*rt].len<mid-l+1) get(l,mid,2*rt);
else get(mid+1,r,2*rt+1);
}
int main(){
scanf("%d%d",&n,&d);
int m=0;
for(int i=1;i<=n;i++){
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x2--;
y2--;
if(x2-x1+1>=d)
x1=0,x2=d-1;
if(y2-y1+1>=d)
y1=0,y2=d-1;
md(x1),md(x2),md(y1),md(y2);
if(x1<=x2)
{
if(y1<=y2) add(x1,y1,x2,y2);
else add(x1,0,x2,y2),add(x1,y1,x2,d-1);
}
else
{
if(y1<=y2) add(0,y1,x2,y2),add(x1,y1,d-1,y2);
else add(0,0,x2,y2),add(x1,y1,d-1,d-1),add(0,y1,x2,d-1),add(x1,0,d-1,y2);
}
}
for(int i=0;i<d;i++)
{
for(int j=0;j<x[i].size();j++){
l1=x[i][j].tl;
r1=x[i][j].tr;
xx=x[i][j].x;
change(0,d-1,1);
}
if(a[1].len<d)
{
printf("YES\n%d ",i);
get(0,d-1,1);
return 0;
}
}
printf("NO\n");
}