• [APIO2019]桥梁


    • 给定边带权的无向图 ((V,E))(q) 次操作,改变一条边的权值或者询问从 (s_i) 出发只走权值大于等于 (w_i) 的边能够到达的点数。
    • (|V| leq 5 imes 10^4, |E|, q leq 10^5)

    分别考虑涉及修改和不涉及修改的边:

    • 对于不涉及修改的边,将询问从大到小排序,然后从大到小加边用并查集维护联通块。这部分是 (O(|E| log |E| + q log q))
    • 对于涉及修改的边,每次询问暴力访问询问之前的修改,满足条件就加入并查集。这部分是 (O(q^2log q))

    将操作分块,设块大小为 (S),第一部分变为 (O(|E|log |E| + S log S)),第二部分变为 (O(S^2log S))

    总复杂度 (O(frac qS|E|log|E| + qSlog S)),大概算一下块大小,卡常。

    #include <bits/stdc++.h>
    #define dbg(...) std::cerr << "33[32;1m", fprintf(stderr, __VA_ARGS__), std::cerr << "33[0m"
    template <class T, class U>
    inline bool smin(T &x, const U &y) { return y < x ? x = y, 1 : 0; }
    template <class T, class U>
    inline bool smax(T &x, const U &y) { return x < y ? x = y, 1 : 0; }
    using LL = long long;
    using PII = std::pair<int, int>;
    
    constexpr int N(5e4 + 5), S(500);
    int fa[N], siz[N];
    int find(int x) {
      while (fa[x] != x) x = fa[x];
      return x;
    }
    int main() {
      std::ios::sync_with_stdio(false);
      std::cin.tie(nullptr);
      int n, m, q;
      std::cin >> n >> m;
      std::vector<std::array<int, 3>> e(m);
      for (auto &[x, y, z] : e) std::cin >> x >> y >> z;
      std::vector<int> eq(m);
      std::iota(eq.begin(), eq.end(), 0);
      auto cmp_edge = [&](int i, int j) { return e[i][2] > e[j][2]; };
      std::sort(eq.begin(), eq.end(), cmp_edge);
      std::cin >> q;
      for (int i = 0; i < q; i += S) {
        std::vector<std::array<int, 3>> a, b;
        std::vector<char> vis(m);
        for (int j = 0; j < S && i + j < q; j++) {
          int t, x, y;
          std::cin >> t >> x >> y;
          if (t == 1) {
            vis[--x] = 1;
            a.push_back({ j, x, y });
          } else {
            b.push_back({ j, x, y });
          }
          (t == 1 ? a : b).push_back({ j, x, y });
        }
        std::sort(b.begin(), b.end(), [](const auto &x, const auto &y) { return x[2] > y[2]; });
        std::vector<int> c, d, ans(a.size() + b.size());
        for (int j = 0; j < m; j++) {
          if (!vis[eq[j]]) {
            c.push_back(eq[j]);
          } else {
            d.push_back(eq[j]);
          }
        }
        std::iota(fa, fa + n + 1, 0);
        std::fill(siz, siz + n + 1, 1);
        auto p = c.begin();
        for (auto &[t, s, w] : b) {
          for (; p != c.end() && e[*p][2] >= w; p++) {
            int x = find(e[*p][0]), y = find(e[*p][1]);
            if (x == y) continue;
            if (siz[x] > siz[y]) std::swap(x, y);
            fa[x] = y, siz[y] += siz[x];
          }
          
          std::vector<int> pre(d.size());
          for (int j = 0; j < d.size(); j++) {
            pre[j] = e[d[j]][2];
          }
          for (auto &[tt, x, y] : a) {
            if (tt > t) continue;
            e[x][2] = y;
          }
          std::vector<std::array<int, 3>> v;
          for (int j : d) {
            if (e[j][2] >= w) {
              int x = find(e[j][0]), y = find(e[j][1]);
              if (x == y) continue;
              if (siz[x] > siz[y]) std::swap(x, y);
              v.push_back({ x, y, fa[x] });
              fa[x] = y, siz[y] += siz[x];
            }
          }
          ans[t] = siz[find(s)];
          while (!v.empty()) {
            auto &[x, y, z] = v.back();
            fa[x] = z, siz[y] -= siz[x];
            v.pop_back();
          }
          for (int j = 0; j < d.size(); j++) {
            e[d[j]][2] = pre[j];
          }
        }
        for (int i : ans) if (i) std::cout << i << "
    ";
        for (auto &[t, x, y] : a) e[x][2] = y;
        std::sort(d.begin(), d.end(), cmp_edge);
        std::merge(c.begin(), c.end(), d.begin(), d.end(), eq.begin(), cmp_edge);
      }
      return 0;
    }
    
    
  • 相关阅读:
    SQL Server公共表表达式简介
    SQL Server实现递归查询(使用公共表表达式)
    Qt 怎么检测鼠标在不在某个控件上
    设计模式之命令模式要听话!
    Leetcode 119. 杨辉三角 II
    C++11智能指针shared_ptr的理解与使用示例
    Qt 纯C++项目发布为dll的方法(超详细步骤)
    error C1041: 无法打开程序数据库“xxx\vc140.pdb”;如果要将多个 CL.EXE 写入同一个 .PDB 文件,请使用/FS(亲测可用)
    WIN1064位编译OpenSSL详细教程
    Qt信号重载需要使用函数指针来实现信号/槽机制
  • 原文地址:https://www.cnblogs.com/HolyK/p/14332957.html
Copyright © 2020-2023  润新知