2021牛客多校6 H、Hopping Rabbit(扫描线)

原题意可以转化为把所有矩形映射到 \(0<=x<=d && 0<=y<=d\) 这个区域内,然后用扫描线判断有没有点没有矩形没有覆盖到,这个点为起点就可以存活。

首先把矩形映射下来是个非常难写的模拟:


vector<line>l;//扫描线的线段
void push(ll x, ll y, ll xx, ll yy)
{
    if (xx - x > 0 && yy - y > 0)
    {
        l.push_back({ y,x,xx,1 });
        l.push_back({ yy,x,xx,-1 });
    }
}
 

cin >> n >> d;
for (int i = 1; i <= n; i++)
    {
        ll x, y, xx, yy;
        cin >> x >> y >> xx >> yy;
        ll dx = xx - x, dy = yy - y;//矩形的长和宽
        Mod(x), Mod(y);//把矩形左下角先映射到扫描区域内
        dx = min(dx, d);
        dy = min(dy, d);//这两个超过d了也等价于他们等于d
        xx = x + dx;//这是再加上长和宽推算出右上角的坐标
        yy = y + dy;
	//然后就是把在扫描区域外的面积映射回去
        if (xx <= d && yy <= d)
            push(x, y, xx, yy);
        else if (xx > d && yy <= d)
        {
            push(x, y, d, yy);
            push(0, y, xx - d, yy);
        }
        else if (yy > d && xx <= d)
        {
            push(x, y, xx, d);
            push(x, 0, xx, yy - d);
        }
        else if (xx > d && yy > d)
        {
            push(x, y, d, d);
            push(x, 0, d, yy - d);
            push(0, y, xx - d, d);
            push(0, 0, xx - d, yy - d);
        }
    }

把这个问题解决之后,就可以把扫描线的板子抄上去查询了:

void check(ll y)//把y从0到d扫描然后check
{
    ll len = t[1].len;
    if (len == d)return;//如果全部覆盖到了就直接return输出no
    int p = 1, l = 1, r = d;//否则就去查询哪个点没覆盖到
    while (t[p].len != 0)
    {
        //cout << l << " " << r << endl;
        int mid = l + r >> 1;
        int ok = mid - l + 1;//左区间全部覆盖到的长度
        int len1 = t[p << 1].len;
        int len2 = t[p << 1 | 1].len;
        if (len1 < ok)//左边没覆盖到
        {
            p = p << 1;
            r = mid;
        }
        else if (len2 < r - mid)
        {
            p = p << 1 | 1;
            l = mid + 1;
        }
    }
    cout << "YES" << endl;
    cout << t[p].l - 1 << " " << y;
    exit(0);
}

AC代码(比赛时由于手残导致赛后过题):

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define fastio ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
#define ll long long
#define ld long double
#define pii pair<int,int>
#define pll pair<ll,ll>

const int maxn = 1e6 + 10;
int N = 1e5 + 10;

int n;
ll d;
void Mod(ll& x)
{
    x = ((x % d) + d) % d;
}

struct line {
    ll y, x, xx, v;
    friend bool operator<(line a, line b)
    {
        return a.y < b.y;
    }
};

struct tree {
    ll l, r;
    ll cnt, len;
}t[maxn];

void pushup(int p)
{
    ll l = t[p].l, r = t[p].r;
    t[p].len = (t[p].cnt ? (r - l + 1) : (t[p << 1].len + t[p << 1 | 1].len));
}

void build(int l, int r, int p)
{
    t[p].l = l, t[p].r = r;
    t[p].cnt = 0, t[p].len = 0;
    if (l == r)return;
    int mid = l + r >> 1;
    build(l, mid, p << 1);
    build(mid + 1, r, p << 1 | 1);
}
void change(int x, int y, ll k, int p)
{
    int l = t[p].l, r = t[p].r;
    if (x <= l && r <= y)
    {
        t[p].cnt += k;
        pushup(p);
        return;
    }
    int mid = l + r >> 1;
    if (x <= mid)change(x, y, k, p << 1);
    if (y > mid)change(x, y, k, p << 1 | 1);
    pushup(p);
}
vector<line>l;

void push(ll x, ll y, ll xx, ll yy)
{
    if (xx - x > 0 && yy - y > 0)
    {
        l.push_back({ y,x,xx,1 });
        l.push_back({ yy,x,xx,-1 });
    }
}

void check(ll y)
{
    ll len = t[1].len;
    //cout << len << endl;
    if (len == d)return;
    int p = 1, l = 1, r = d;
    while (t[p].len != 0)
    {
        //cout << l << " " << r << endl;
        int mid = l + r >> 1;
        int ok = mid - l + 1;
        int len1 = t[p << 1].len;
        int len2 = t[p << 1 | 1].len;
        if (len1 < ok)
        {
            p = p << 1;
            r = mid;
        }
        else if (len2 < r - mid)
        {
            p = p << 1 | 1;
            l = mid + 1;
        }
    }
    cout << "YES" << endl;
    cout << t[p].l - 1 << " " << y;
    exit(0);
}

int main()
{
    /*
    3 3
    0 0 1 1
    0 0 3 2
    1 0 2 3
    */
    //freopen("C:\\out.txt", "w", stdout);
    fastio;
    cin >> n >> d;
    for (int i = 1; i <= n; i++)
    {
        ll x, y, xx, yy;
        cin >> x >> y >> xx >> yy;
        ll dx = xx - x, dy = yy - y;
        Mod(x), Mod(y);
        dx = min(dx, d);
        dy = min(dy, d);
        xx = x + dx;
        yy = y + dy;
        if (xx <= d && yy <= d)
            push(x, y, xx, yy);
        else if (xx > d && yy <= d)
        {
            push(x, y, d, yy);
            push(0, y, xx - d, yy);
        }
        else if (yy > d && xx <= d)
        {
            push(x, y, xx, d);
            push(x, 0, xx, yy - d);
        }
        else if (xx > d && yy > d)
        {
            push(x, y, d, d);
            push(x, 0, d, yy - d);
            push(0, y, xx - d, d);
            push(0, 0, xx - d, yy - d);
        }
    }
    sort(l.begin(), l.end());
    build(1, d, 1);
    int i = 0;
    for (int y = 0; y < d; y++)
    {
        while (i < l.size() && l[i].y == y)
        {
            //cout << l[i].x << " " << l[i].xx<<" "<<l[i].v << endl;
            change(l[i].x + 1, l[i].xx, l[i].v, 1);
            i++;
        }
        check(y);
    }
    cout << "NO";
    return 0;

}

posted @ 2021-08-19 23:04  Lecoww  阅读(59)  评论(0编辑  收藏  举报