嘘~ 正在从服务器偷取页面 . . .

洛谷P7973 [KSN2021] Binary Land 题解


洛谷P7973 [KSN2021] Binary Land 题解

题目链接:P7973 [KSN2021] Binary Land

题意

给定一张 $N$ 个点的图,每个点有权值 $A_i$ 和价值 $B_i$。

两个点 $x,y$ 之间存在一条无向边当且仅当 $A_x\text{ xor }A_y>\max(A_x,A_y)$。

你需要对于 $i=1,2,\cdots n$ 依次求出点 $i$ 所在连通块中所有点的价值和。

输入格式

第一行输入一个正整数 $N$。

第二行输入 $N$ 个正整数 $A_i$。

第三行输入 $N$ 个正整数 $B_i$。

输出格式

输出 $N$ 行,第 $i$ 行包含一个整数,代表点 $i$ 所在连通块中所有点的价值和。

数据范围

对于所有数据,$1 \leq N \leq 10^5$,$1 \leq A_i \leq 2^{30}-1$,$1 \leq B_i \leq 10^9$。

根据常规套路,钦定 $A_x \ge A_y$ ,则边 $(x,y)$ 存在的充要条件为:$A_x$ 的第 「 $A_y$ 的最高位 」位为 $0$ 。

容易证明这种情况下,$A_x \operatorname{xor} A_y > A_x$ 。但是因为 $y$ 的数量很多,所以考虑用并查集维护连通性。

直接把 $x,y$ 合并并不是很方便统计,我们可以加入 $64$ 个点,表示每一个二进制位,然后通过他们连接 $x,y$ 。

时间复杂度 $\mathcal{O}(n \log^2 n)$

代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
void up(int &x,int y) { x < y ? x = y : 0; }
void down(int &x,int y) { x > y ? x = y : 0; }
#define N ((int)(1e5 + 225))

char vis1[35],vis2[35];
int n,a[N],b[N],f[N],val[N],hib[N];
void init() { for(int i = 1; i <= n + 66; i++) f[i] = i; }
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
void merge(int x,int y) {
    x = find(x), y = find(y); if(x != y) { f[x] = y; val[y] += val[x]; }
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    cin >> n; init();
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) { cin >> b[i], val[i] = b[i]; }
    for(int i = 1; i <= n; i++)
    {
        int j = 64 - __builtin_clzll(a[i]);
        vis1[j] = true; hib[i] = j;
        while(j--) if(!(a[i] & (1 << (j - 1)))) vis2[j] = true;
    }
    for(int i = 1; i <= n; i++)
    {
        if(vis2[hib[i]]) merge(i, hib[i] + n);
        for(int j = 64 - __builtin_clzll(a[i]); j; j--) {
            if(!(a[i] & (1 << (j - 1))) && vis1[j]) merge(i, j + n);
        }
    }
    for(int i = 1; i <= n; i++) cout << val[find(i)] << '\n';
    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录