Codeforces Round 886 (Div. 4)

发布时间 2023-07-22 10:56:22作者: Zeoy_kkk

F. We Were Both Children

image-20230722103513062

题解:约数

  • 我们先利用\(map\)记录\(a_i\)的出现次数
  • 然后对\(map\)中的每一个元素的在其所有不超过\(n\)的倍数的位置上都加上对应的贡献
  • 时间复杂度:调和级数\(O(nlogn)\)
const int N = 2e5 + 10, M = 4e5 + 10;

int n;
int a[N];
map<int, int> mp;

void solve()
{
    cin >> n;
    mp.clear();
    for (int i = 1; i <= n; ++i)
    {
        cin >> a[i];
        mp[a[i]]++;
    }
    vector<int> ans(n + 10);
    for (auto [x, y] : mp)
        for (int j = x; j <= n; j += x)
            ans[j] += y;

    int res = 0;
    for (int i = 1; i <= n; ++i)
        res = max(res, ans[i]);
    cout << res << endl;
}

G. The Morning Star

image-20230722104226994

题解:\(map\) + 组合计数

  • 我们开\(4\)\(map\)记录四个方向上点的数量
  • 假设每一个方向上的点数为\(x\),显然每一个方向上的方案数为\(x \times (x - 1)\)
const int N = 2e5 + 10, M = 4e5 + 10;

int n;
map<int, int> mp[4];

void solve()
{
    cin >> n;
    mp[0].clear();
    mp[1].clear();
    mp[2].clear();
    mp[3].clear();
    for (int i = 1; i <= n; ++i)
    {
        int x, y;
        cin >> x >> y;
        mp[0][x]++;
        mp[1][y]++;
        mp[2][y - x + n]++;
        mp[3][y + x]++;
    }
    int ans = 0;
    for (auto [x, y] : mp[0])
        if (y)
            ans += y * (y - 1);
    for (auto [x, y] : mp[1])
        if (y)
            ans += y * (y - 1);
    for (auto [x, y] : mp[2])
        if (y)
            ans += y * (y - 1);
    for (auto [x, y] : mp[3])
        if (y)
            ans += y * (y - 1);
    cout << ans << endl;
}

H. The Third Letter

image-20230722104617379

题解:带权并查集

  • 我们考虑带权并查集做法

  • 并查集中维护每个点到根节点的距离为\(dis_u\)

  • 显然如果两个士兵\(u,v\)有关系的话,那么根据简单容斥得到,两者之间的距离为\(dis_u - dis_v\)

  • 对于两个士兵\(u,v\)来说,如果当前没有关系,那么合并两个点,即将\(u\)的根节点\(fu\)合并到\(v\)的根节点\(fv\)上去,我们考虑如何构造\(dis_{fu}\)

\[dis_u + dis_{fu} - dis_v = w\\ dis_{fu} = dis_v - dis_u + w \]

  • 那么如果两个士兵有关系的话,判断两者之间的距离是否合法即可
const int N = 2e5 + 10, M = 4e5 + 10;

int n, m;

// 带权并查集
struct DSU
{
    int fa[N], dis[N];
    void init()
    {
        for (int i = 1; i <= n; ++i)
        {
            fa[i] = i;
            dis[i] = 0;
        }
    }
    int find(int x)
    {
        if (x == fa[x])
            return x;
        int rt = find(fa[x]);
        dis[x] += dis[fa[x]];
        fa[x] = rt;
        return fa[x];
    }
    void merge(int u, int v, int w)
    {
        int fu = find(u);
        int fv = find(v);
        if (fu != fv)
        {
            fa[fu] = fv;
            // dis[u] + dis[fu] - dis[v] = w;
            dis[fu] = dis[v] - dis[u] + w;
        }
    }
} dsu;

void solve()
{
    cin >> n >> m;
    dsu.init();
    bool flag = true;
    for (int i = 1; i <= m; ++i)
    {
        int u, v, w;
        cin >> u >> v >> w;
        if (dsu.find(u) != dsu.find(v))
            dsu.merge(v, u, w);
        else
        {
            if (dsu.dis[v] - dsu.dis[u] != w)
                flag = false;
        }
    }
    if (flag)
        cout << "YES" << endl;
    else
        cout << "NO" << endl;
}