[模拟赛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;
}

posted @ 2020-10-24 23:07  luyiming123  阅读(67)  评论(0编辑  收藏  举报