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

洛谷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 !
评论
  目录