简要题意:

昨天写了原题,有感,故有此题解🤭
本题有两个操作:
1.attack–>占领(x,y),意味着消除和周围已经占领的坐标之间的墙
2.query–>查询(x,y)所在连通块有多少面墙
这两个需求都可以用并查集来维护


数据结构:

我们可以封装一个并查集类,支持查找,合并,返回必要的值

class DSU {
    private:
        int n;
        std::vector<int> f,sz,rst;
    public:
        inline void init(int n_) {
            this->n = n_;
            f.assign(n+1,0);  sz.assign(n+1,1);  rst.assign(n+1,0);
            std::iota(f.begin(),f.end(),0);
        }
        int find(int u) {
            return f[u] == u ? u : f[u] = find(f[u]);
        }
        void merge(const int u,const int v) {
            int fu = find(u),fv = find(v);
            if (fu != fv) {
                f[fv] = fu;  sz[fu] += sz[fv];   rst[fu] += rst[fv] + 2;
            }else   rst[fu] += 2;
        }
        int get_sz(int pos) { return this->sz[pos]; }
        int get_rst(int pos) { return this->rst[pos]; }
}dsu;

处理技巧:

由于本题是二维坐标,我们需要用std::map来动态地为每个坐标开点,将二维坐标转换为线性的一维坐标.

mp[{x,y}] = ++cnt;

答案统计:

对于查询的坐标(x,y),如果(x,y)所在的连通块只有它自己,那么答案就是6.为什么呢?
原因很简单,因为(x,y)附近的点都没有被攻击,所以(x,y)的六条边都不会被消除
否则:答案就是6 * (x,y)所在的连通块的点的数量 - 2 * 重复的数量(本题的核心)

完整代码(已经AC):

#include <bits/stdc++.h>
using ll = long long signed int;
#define lowbit(x) ((x)&-(x))
#define pi std::acos(-1.0)
#define pii std::pair<int,int>
#define mst(x) std::memset(x,0,sizeof(x))
#define IOS std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
#define mid ((l+r)>>1)
const int inf = 0x3f3f3f3f;
const ll linf = 0x3f3f3f3f3f3f3f3f;
const int N = 500005;
class DSU {
    private:
        int n;
        std::vector<int> f,sz,rst;
    public:
        inline void init(int n_) {
            this->n = n_;
            f.assign(n+1,0);  sz.assign(n+1,1);  rst.assign(n+1,0);
            std::iota(f.begin(),f.end(),0);
        }
        int find(int u) {
            return f[u] == u ? u : f[u] = find(f[u]);
        }
        void merge(const int u,const int v) {
            int fu = find(u),fv = find(v);
            if (fu != fv) {
                f[fv] = fu;  sz[fu] += sz[fv];   rst[fu] += rst[fv] + 2;
            }else   rst[fu] += 2;
        }
        int get_sz(int pos) { return this->sz[pos]; }
        int get_rst(int pos) { return this->rst[pos]; }
}dsu;
int cnt;
int nxts[][2] = {1,0,1,-1,0,-1,-1,0,-1,1,0,1};
std::map<pii,int> mp;
void solve();
int main() {
    IOS;    int T = 1;
    while (T--)   solve();
    return 0;
}
void solve() {
    int q;   std::cin >> q;
    dsu.init(q);

    while (q--) {
        int op,x,y;    std::cin >> op >> x >> y;

        if (op == 1) {
            mp[{x,y}] = ++cnt;
            for (int i = 0; i < 6; ++i) {
                int tx = x + nxts[i][0];
                int ty = y + nxts[i][1];

                if (mp.find({tx,ty}) == mp.end())   continue;
                dsu.merge(cnt,mp[{tx,ty}]);
            }
        }
        else if (op == 2) {
            int fx = dsu.find(mp[{x,y}]);

            if (dsu.get_sz(fx) == 1)   std::cout << 6 << "\n";
            else  std::cout << (6 * dsu.get_sz(fx) - dsu.get_rst(fx)) << "\n";
        }
    }
}
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐