并查集——E.Merging Towers

本文介绍了并查集解决E.Merging Towers问题的思路。通过将相邻的碟子视为一个整体,可以减少操作次数。利用并查集建立树结构,每次合并时检查小树中节点与其相邻节点的祖先,若相邻则减少答案并更新祖先节点。
摘要由CSDN通过智能技术生成

题解:

神奇的一道题,首先我们考虑如果我们一个个的搬这个碟子的话答案是n-1,但是如果我们有两个相邻的碟子是临近的那么就可以把他们看成一个整体这样的话答案就可以减去1了。我们按照每堆的top点建立树,每次合并的时候,对于小树的每个节点我们都判断它在原数组的相邻节点的祖先节点是不是合并的大树top点,如果是的既然相邻那么他们的半径就是差值最小的,也就是说可以把他们看成一个整体了答案就可以减去1了,然后再改变小树的祖先节点和原数组中记录的top节点改变就行了。

#include<bits/stdc++.h>
using namespace std;
//#define int long long
typedef long long ll;
typedef long double ld;
const int N=2e5+10;
int pos[N],pre[N];
vector<int> g[N];
int find(int x)
{
    if(x==pre[x]) return pre[x];
    return pre[x]=find(pre[x]);
}
signed main()
{
    int n,m; scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++) {
        scanf("%d",&pos[i]); pos[i]--;
        g[pos[i]].push_back(i);
    }
    int res=n-1;
    for(int i=0;i<m;i++) pre[i]=i;
    for(int i=1;i<n;i++) {
        if(pos[i-1]==pos[i]) res--;
    }
    printf("%d\n",res);
    for(int i=0;i<m-1;i++){
        int a,b; scanf("%d%d",&a,&b); a--,b--;
        int u=find(a),v=find(b);
        if((int)g[u].size()>(int) g[v].size()) swap(u,v);
        for(auto it:g[u]){
            if(it+1<n&&pos[it+1]==v) res--;
            if(it-1>=0&&pos[it-1]==v) res--;
            g[v].push_back(it);
        }
        for(auto it:g[u]) pos[it]=v;
//        g[u].clear();
        pre[u]=v;
        printf("%d\n",res);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值