题目描述
给定一张 NN 个点的图,每个点有权值 A_iAi 和价值 B_iBi。
两个点 x,yx,y 之间存在一条无向边当且仅当 A_x\text{ xor }A_y>\max(A_x,A_y)Ax xor Ay>max(Ax,Ay)。
你需要对于 i=1,2,\cdots ni=1,2,⋯n 依次求出点 ii 所在连通块中所有点的价值和。
输入格式
第一行输入一个正整数 NN。
第二行输入 NN 个正整数 A_iAi。
第三行输入 NN 个正整数 B_iBi。
输出格式
输出 NN 行,第 ii 行包含一个整数,代表点 ii 所在连通块中所有点的价值和。
输入输出样例
输入 #1复制
3 2 1 1 20 30 10
输出 #1复制
60 60 60
输入 #2复制
4 5 4 4 5 10 20 30 40
输出 #2复制
10 20 30 40
输入 #3复制
5 1 2 1 7 11 20 10 30 100 100
输出 #3复制
60 60 60 200 200
说明/提示
【数据范围】
本题采用捆绑测试。
- Subtask 1(8 points):只存在一组数据,满足 N=8N=8,A=[6,39,11,63,3,39,1,43]A=[6,39,11,63,3,39,1,43],B=[4,8,3,7,9,1,2,2]B=[4,8,3,7,9,1,2,2]。
- Subtask 2(13 points):保证 N \leq 200N≤200。
- Subtask 3(10 points):保证 N \leq 2000N≤2000。
- Subtask 4(4 points):保证 A_1=A_2=\cdots=A_nA1=A2=⋯=An。
- Subtask 5(7 points):保证存在非负整数 kk 使得 A_i=2^kAi=2k。
- Subtask 6(19 points):A_i\leq 2^{12}-1Ai≤212−1。
- Subtask 7(39 points):无特殊限制。
对于所有数据,1 \leq N \leq 10^51≤N≤105,1 \leq A_i \leq 2^{30}-11≤Ai≤230−1,1 \leq B_i \leq 10^91≤Bi≤109。
上代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e6;
int n, a[N], w[N];
int f[N];
bool vis1[N], vis2[N];
int find(int x) {
if (f[x] == x) return x;
return f[x] = find(f[x]);
}
void merge(int u, int v) {
int t1 = find(u), t2 = find(v);
if (t1 != t2) {
f[t1] = t2;
w[t2] += w[t1];
}
}
signed main() {
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
for (int i = 1; i <= n; ++i) {
cin >> w[i];
}
for (int i = 1; i <= n + 35; ++i) {
f[i] = i;
}
for (int k = 1; k <= n; ++k) {
int zgwk = (int)(log2(a[k])+1e-10);
vis1[zgwk] = 1;
}
for (int i = 1; i <= n; ++i) {
int zgw = (int)(log2(a[i])+1e-10);
for (int j = zgw - 1; j >= 0; --j) {
if (!(a[i] >> j & 1)) {
vis2[j] = 1;
}
}
}
for (int k = 1; k <= n; ++k) {
int zgwk = (int)(log2(a[k])+1e-10);
if(!vis1[zgwk]||!vis2[zgwk])continue;
merge(zgwk + n + 1, k);
}
for (int i = 1; i <= n; ++i) {
int zgw = (int)(log2(a[i])+1e-10);
for (int j = zgw - 1; j >= 0; --j) {
if (!(a[i] >> j & 1)) {
if(!vis1[j]||!vis2[j])continue;
merge(j + n + 1, i);
}
}
}
for (int i = 1; i <= n; ++i) {
cout << w[find(i)] << endl;
}
return 0;
}