[SDCPC2023] Not Another Path Query Problem

还记得如何比较两个数的大小吗?在两个数数位长度都相同的情况下,从高位开始依次比较。题目中数据的值域为 ,我们比较最多约 次即可得知答案。

我们依次考虑 二进制前缀的若干位。

个并查集。对于长度为 后缀,我们将其最后一位强制赋上 ,记这个值为
然后,倘若当前边长度为 的后缀中, 所有为 的位 都为 ,就把这条边加进并查集 。这样,可以保证并查集 所有边之与运算之和,其长度为 的前缀大于等于

证明:二进制意义下, 的一个必要条件是存在某一位 的第 位为 的第 位为 。而在我们的操作中,保证了 的所有位,边权的当前位也必定为 。该必要条件无法被满足。

查询时,从高位到低位扫一遍 个并查集。若能遍历到这一位,说明我们已经考虑过前面的位了,只关心这一位的内容即可。每一位根据 的二进制位分类讨论:

  • 的当前位为 :我们加入并查集的时候最后一位被修改为了 。倘若并查集告诉我们这两个点联通,则这两点之间存在一条略大于 的路径,直接打飞,否则继续枚举;
  • 的当前位为 :此时并查集存入的正是 的前缀。若两点不联通,就肯定不存在大于等于 的路径了,直接打飞,否则继续枚举。

不过,这套方法只能考虑到是否存在大于 的边。特殊处理一下,再单独拉个并查集把等于的扔进去就对了。

#include <cstddef>
#include <iostream>
#include <vector>
using namespace std;
istream& fin = cin;
ostream& fout = cout;
using ui = unsigned int;
using uli = unsigned long long int;
using li = long long int;
using Graph = vector<vector<size_t>>;
struct DSU {
  vector<ptrdiff_t> fa;
  DSU(size_t n): fa(n, -1) {}
  size_t find(size_t x) { return fa[x] < 0 ? x : fa[x] = find(fa[x]); }
  size_t setSize(size_t x) { return -fa[find(x)]; }
  bool check(size_t x, size_t y) { return find(x) == find(y); }
  void merge(size_t x, size_t y) {
    if (check(x, y)) return;
    if (setSize(x) > setSize(y)) swap(x, y);
    fa[find(y)] -= setSize(x);
    fa[find(x)] = find(y);
  }
};
int main(void) {
  ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  size_t n, m, q;
  uli k;
  fin >> n >> m >> q >> k;
  vector<DSU> ds(61, DSU{n});
  while (m--) {
    size_t u, v;
    uli w;
    fin >> u >> v >> w;
    --u, --v;
    for (size_t i = 0; i < 60; ++i)
      if (((w >> i) & (k >> i | 1)) == (k >> i | 1)) ds[i].merge(u, v);
    if ((w & k) == k) ds[60].merge(u, v);
  }
  while (q--) {
    size_t x, y;
    fin >> x >> y;
    --x, --y;
    if (ds[60].check(x, y)) goto yes;
    for (size_t i = 59; i < 60; --i) {
      bool tst = ds[i].check(x, y);
      if (((k >> i) & 1) && !tst) goto no;
      if (!((k >> i) & 1) && tst) goto yes;
    }
  no:
    fout << "No\n";
    continue;
  yes:
    fout << "Yes\n";
  }
  return 0;
}
posted @ 2024-10-19 01:20  MrPython  阅读(6)  评论(0)    收藏  举报  来源