1 条题解

  • 0
    @ 2025-8-24 22:56:27

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Jerrywang09
    Пусть сильнее грянет буря!

    搬运于2025-08-24 22:56:27,当前版本为作者最后更新于2024-04-21 17:49:58,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    阅读题解前请确保完全理解题面。

    首先有一个性质,想不到就没法做题了:假设有柱子 (x,y1),(x,y2),(x,y3),(x,y4),(x,y_1),(x,y_2),(x,y_3),(x,y_4),\cdots 有着相同的横坐标,一定是形如 (x,y2k1),(x,y2k)(x,y_{2k-1}),(x,y_{2k}) 的一对柱子中间连了栅栏,形如 (x,y2k),(x,y2k+1)(x,y_{2k}),(x,y_{2k+1}) 的一对柱子中间一定没连。对于有相同纵坐标的同理。

    剩下的比较套路。连边后构成一个环图,dfs 找出环的顺序,破环成链,用差分维护区间修改即可。代码很难写。

    在实现中,我将询问中的点与柱子一起处理。然后对于同一行(列)的点,找到相邻的两个柱子,并把其间的询问点一起连上。迭代器的处理也很繁琐。

    如何处理重复的点也是个问题。各数组的含义详见代码注释。

    // Title:  Painting Fence Posts
    // Source: USACO24OPEN Silver
    // Author: Jerrywang
    #include <bits/stdc++.h>
    #define F first
    #define S second
    #define pii pair<int, int>
    #define ll long long
    #define rep(i, s, t) for(int i=s; i<=t; ++i)
    #define debug(x) cerr<<#x<<":"<<x<<endl;
    const int N=1000010;
    using namespace std;
    
    int n, nn, m;
    map<int, set<int>> row, col;
    // row,col:   相同行(列)上的点的列(行)坐标
    map<pii, int> id; pii point[N];
    // point[i]:  原始编号为i的点的坐标
    // id[{x,y}]: 坐标为(x,y)的点的最小原始编号
    vector<int> g[N]; int a[N], a_id[N], cnt[N]; ll d[N];
    // a[i]:      环上编号为i的点的原始编号
    // a_id[i]:   原始编号为i的点的环上编号
    ll dis(pii a, pii b)
    {
        return abs(a.F-b.F)+abs(a.S-b.S);
    }
    void add(int u, int v)
    {
        g[u].push_back(v), g[v].push_back(u);
    }
    bool vis[N];
    void dfs(int u)
    {
        a[++nn]=u; vis[u]=1;
        for(int v:g[u]) if(!vis[v]) dfs(v);
    }
    
    int main()
    {
        #ifdef Jerrywang
        freopen("E:/OI/in.txt", "r", stdin);
        #endif
        scanf("%d%d", &m, &n);
        rep(i, 1, n)
        {
            int x, y; scanf("%d%d", &x, &y);
            id[{x, y}]=i, point[i]={x, y};
            row[x].insert(y), col[y].insert(x);
        }
        rep(i, 1, m)
        {
            int x1, y1, x2, y2; scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
            point[n+i]={x1, y1}, point[n+m+i]={x2, y2};
            if(!id[{x1, y1}])
                id[{x1, y1}]=n+i,   row[x1].insert(y1), col[y1].insert(x1);
            if(!id[{x2, y2}])
                id[{x2, y2}]=n+m+i, row[x2].insert(y2), col[y2].insert(x2);
        }
        for(auto &[x,S]:row)
        {
            auto i=S.begin();
            while(i!=S.end())
            {
                for(; i!=S.end(); i++) if(id[{x, *i}]<=n) break;
                auto j=next(i), k=i;
                for(; j!=S.end(); j++) if(id[{x, *j}]<=n) break;
                if(j==S.end()) break;
                for(; k!=j; k++) add(id[{x, *k}], id[{x, *next(k)}]);
                i=next(j);
            }
        }
        for(auto &[y,S]:col)
        {
            auto i=S.begin();
            while(i!=S.end())
            {
                for(; i!=S.end(); i++) if(id[{*i, y}]<=n) break;
                auto j=next(i), k=i;
                for(; j!=S.end(); j++) if(id[{*j, y}]<=n) break;
                if(j==S.end()) break;
                for(; k!=j; k++) add(id[{*k, y}], id[{*next(k), y}]);
                i=next(j);
            }
        }
        dfs(1);
        rep(i, 1, nn) a[nn+i]=a[i], a_id[a[i]]=i;
        rep(i, 2, nn+nn) d[i]=dis(point[a[i]], point[a[i-1]]), d[i]+=d[i-1];
        rep(i, 1, m)
        {
            int u=a_id[id[point[n+i]]], v=a_id[id[point[n+m+i]]];
            ll d1, d2;
            if(d[u]<d[v])
            {
                d1=d[v]-d[u], d2=d[nn+u]-d[v];
                if(d1<d2)
                    cnt[u]++, cnt[v+1]--;
                else
                    cnt[v]++, cnt[nn+u+1]--;
            }
            else
            {
                d1=d[u]-d[v], d2=d[nn+v]-d[u];
                if(d1<d2)
                    cnt[v]++, cnt[u+1]--;
                else
                    cnt[u]++, cnt[nn+v+1]--;
            }
        }
        rep(i, 1, nn+nn) cnt[i]+=cnt[i-1];
        rep(i, 1, n)
            printf("%d\n", cnt[a_id[i]]+cnt[nn+a_id[i]]);
        
        return 0;
    }
    
    • 1

    信息

    ID
    9921
    时间
    3000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者