• 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;
    
    }
    
    
  • 相关阅读:
    (项目)在线教育平台(四)
    (项目)在线教育平台(三)
    (项目)在线教育平台(二)
    (项目)在线教育平台(一)
    (面试题)python面试题集锦-附答案
    (python)面向对象
    (python)数据结构---元组
    myEclipse 配置tomcat清除缓存
    Jquery浅克隆与深克隆
    列表上下无缝滚动
  • 原文地址:https://www.cnblogs.com/ruanbaiQAQ/p/15164456.html
Copyright © 2020-2023  润新知