补题ing 参考资料:扫描线问题转化
关于扫描线部分的学习放在散题里。
题意:给出平面上的n个矩形,一只兔子从 ( x 0 + 0.5 , y 0 + 0.5 ) (x_0+0.5,y_0+0.5) (x0+0.5,y0+0.5)出发,每一次可以平行于x轴或y轴跳跃 d 的距离,求出一个初始位置使得它不管怎么跳都不会跳入到陷阱中。注意只有着陆点在陷阱里才算落入陷阱,在空中越过陷阱不算。
数据范围 n, d <= 1e5,平面坐标在-1e9 到 1e9当中。
分析:
在d × d的正方形,有没有一个点没有被移动过的矩形覆盖,有,直接输出即可。另外有一点需要注意,就是一些在d × d正方形边上的矩形的转移(以图中,绿色矩形为例),这些矩形需要特殊的处理,由于这个题是按d × d正方形扫描到,所以不需要离散化,用一个桶来装,然后沿x轴向右扫描即可。
accode:
#include <bits/stdc++.h>
#define re int
#define ll long long
#define int long long
#define ls(p) p<<1
#define rs(p) p<<1|1
#define eps 1e-8
#define pi acos(-1.0)
#define P pair<int, int>
#define pb push_back
using namespace std;
const int mod = 1e9 + 7;
const int N = 3e6 + 5;
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 build(int p, int l, int r)
{
e[p].l = l;
e[p].r = r;
if(l == r) return ;
int mid = (l+r) >> 1;
build(ls(p), l, mid);
build(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("%d %d %d %d", &x1, &y1, &x2, &y2);
x2--, y2--;
if(x2 - x1 + 1 >= d) x1 = 0, x2 = d - 1;
if(y2 - y2 + 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);
}
}
build(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()
{
solve();
return 0;
}