[模拟赛20190808T] merge
题目
Re-see 特别喜欢柠檬。
Re-see 一共采了 n 个柠檬。一开始每个柠檬自成一堆。之后她又做了 Q 次操
作
1 x y:Re-see 觉得不够酸爽,决定把第 x 个柠檬和第 y 个柠檬所在的柠檬
堆合并
特别的,如果 x,y 本来就在一堆里,那么什么也不做
2 a b:Re-see 酸了,对第 a 个柠檬所在的柠檬堆中每个柠檬挤了 b 毫升柠
檬汁喝
Re-see 操作完后决定吃柠檬,请你回答此时每个柠檬被挤了多少毫升柠檬汁
并查集,然后dfs更新。
# include <bits/stdc++.h>
// # include <time.h
using namespace std;
const int N = 3000005;
void FIO(void)
{
freopen("merge.in","r",stdin);
freopen("merge.out","w",stdout);
}
template <typename T> void read(T &x){
int f=1;x=0;char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-f;
for (; isdigit(c);c=getchar()) x=x*10+c-'0';
x*=f;
}
void write(long long x)
{
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x / 10);
putchar((x % 10) + 48);
}
int n,q;
int f[N];
int s[N][2];
int find(int x)
{
if(x ^ f[x]) f[x] = find(f[x]);
return f[x];
}
int ans[N];
int tot = 0;
void bfs(void)
{
queue <int> q;
for(int i = n + 1; i <= tot; i++)
{
if(f[i] == i) q.push(i);
}
while(!q.empty())
{
int head = q.front();q.pop();
if(head > n)
{
ans[s[head][0]] += ans[head];
ans[s[head][1]] += ans[head];
if(s[head][0] > n) q.push(s[head][0]);
if(s[head][1] > n) q.push(s[head][1]);
}
}
return;
}
int main(void)
{
FIO();
read(n),read(q);
for(int i = 1; i <= n + q; i++) f[i] = i;
tot = n;
while(q--)
{
int opt,x,y;
read(opt),read(x),read(y);
if(opt == 1)
{
int fx = find(x),fy = find(y);
if(fx == fy)
{
continue;
}
f[fx] = f[fy] = ++tot;
s[tot][0] = fx,s[tot][1] = fy;
}
else
{
int fx = find(x);
ans[fx] += y;
}
}
bfs();
for(int i = 1; i <= n; i++)
{
write(ans[i]);
putchar(' ');
}
return 0;
}