洛谷——P1196 [NOI2002]银河英雄传说

P1196 [NOI2002]银河英雄传说

 

题目大意:

给你一个序列,支持两种操作:

合并指令为$M_{i,j}$j,含义为第i号战舰所在的整个战舰队列,作为一个整体(头在前尾在后)接至第j号战舰所在的战舰队列的尾部。

$C_{i,j}$该指令意思是,询问电脑,杨威利的第ii号战舰与第jj号战舰当前是否在同一列中,如果在同一列中,那么它们之间布置有多少战舰。

 

据说是带权并查集,其实就是多维护了几个变量而已,

fa[x]依旧表示x的父亲,front[x]表示x与x队头之间的距离,num[x]表示以x为队头的队列中战舰的数量

重点在于如何维护front

显然在合并过程中front和num是在改变的

考虑如果将x与y合并,其队头分别为fx和fy

首先更新fx的父亲,其次更新front[fx],更新的是放在队尾的队头,front[fx]+=num[fy]

再更新fy的队列战舰数量,num[fy]+=num[fx],num[fx]=0

 

这个过程中,显然只有处在对头的front被更新了,那么处在队列其他位置的front如何更新呢

这个就需要在find操作中实现

front[x]+=front[fa[x]];

 

#include<bits/stdc++.h>

#define N 500000
using namespace std;

int T,fa[N],num[N],front[N];
//front[x]表示x与x队头之间的距离 
//num[x]表示以x为队头的队列长度 
int find(int x){
    if(fa[x]==x) return x;
    int f=find(fa[x]);
    front[x]+=front[fa[x]];
    return fa[x]=f;
}

int main()
{
    scanf("%d",&T);
    for(int i=1;i<N;i++) fa[i]=i,num[i]=1;
    while(T--){
        char x;
        cin>>x;
        int i,j;
        scanf("%d%d",&i,&j);
        int fx=find(i),fy=find(j);
        if(x=='C'){
            if(fx!=fy) printf("-1\n");
            else printf("%d\n",abs(front[i]-front[j])-1);
        }else {
            fa[fx]=fy;
            front[fx]+=num[fy];//更新距离 
            num[fy]+=num[fx];//更新队列长度 
            num[fx]=0;//0
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/song-/p/9620959.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值