问题大意
平面上有 n n n个矩形,每个矩形给出左下角的坐标和右上角的坐标,有一只兔子每次可以沿 x x x轴,或 y y y轴跳动长度为 d d d的距离(移动时可以跳过矩形,但落下时不能落在举行以内),问平面上是否存在一点,使得兔子能够走出整个区域,如果能,就任意输出一个能满足上述
扫描线问题转化,其关键在于如何将问题进行转化,转化方式为下
所以问题就是找,在 d ∗ d d*d d∗d的正方形,有没有一个点没有被移动过的矩形覆盖,有,直接输出即可,就是面积并
另外有一点需要注意,就是一些在 d ∗ d d*d d∗d正方形边上的矩形的转移(以图中,绿色矩形为例),这些矩形需要特殊的处理
由于这个题是按 d ∗ d d*d d∗d正方形扫描到,所以不需要离散化,用一个桶来装,然后沿x轴向右扫描就行了
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
#define re int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
const int mod=1e9+7;
const int M=1e8+5;
const int N=3e6+5;//?????????? 4e8
int n,d,t;
struct L
{
int y1,y2,state;
};
struct node
{
int l,r,sum,add;
}e[N];
vector < L > v[N];
int get(int x)
{
x%=d;
if(x<0) x+=d;
return x;
}
void add(int x1,int y1,int x2,int y2)
{
v[x1].pb((L){y1,y2,1});
v[x2+1].pb((L){y1,y2,-1});
}
void bulid(int p,int l,int r)
{
e[p].l=l;e[p].r=r;
if(l==r) return;
int mid=(l+r)>>1;
bulid(ls(p),l,mid);bulid(rs(p),mid+1,r);
}
void push(int p)
{
if(e[p].add) e[p].sum=e[p].r-e[p].l+1;
else if(e[p].l==e[p].r) e[p].sum=0;
else e[p].sum=e[ls(p)].sum+e[rs(p)].sum;
}
void update(int p,int l,int r,int val)
{
if(l<=e[p].l&&e[p].r<=r)
{
e[p].add+=val;
push(p);
return;
}
int mid=(e[p].l+e[p].r)>>1;
if(l<=mid) update(ls(p),l,r,val);
if(mid<r) update(rs(p),l,r,val);
push(p);
}
void print(int p)
{
if(e[p].sum==0)
{
printf("%lld\n",e[p].l);
return;
}
int mid=(e[p].l+e[p].r)>>1;
if(e[ls(p)].sum<mid-e[p].l+1) print(ls(p));
else print(rs(p));
}
void solve()
{
cin>>n>>d;
for(re i=1;i<=n;i++)
{
int x1,y1,x2,y2;
scanf("%lld%lld%lld%lld",&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;
x1=get(x1),y1=get(y1),x2=get(x2),y2=get(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);
}
}
bulid(1,0,d-1);
for(re i=0;i<=d-1;i++)
{
int sz=v[i].size();
for(re j=0;j<sz;j++) update(1,v[i][j].y1,v[i][j].y2,v[i][j].state);
if(e[1].sum<d)
{
puts("YES");
printf("%lld ",i);
print(1);
return;
}
}
puts("NO");
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
// printf("Case %d:\n",index);
solve();
// puts("");
}
return 0;
}
/*
1
6 5
0 0 0 122 499 8888
*/