zoukankan      html  css  js  c++  java
  • 洛谷——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
    ");
                else printf("%d
    ",abs(front[i]-front[j])-1);
            }else {
                fa[fx]=fy;
                front[fx]+=num[fy];//更新距离 
                num[fy]+=num[fx];//更新队列长度 
                num[fx]=0;//0
            }
        }
        return 0;
    }
  • 相关阅读:
    AJAX初识
    PE文件---导入表,导出表
    PE文件学习(基础)
    Android so(ELF)文件解析
    安卓加固方案从落地加载到类指令抽取编写报告
    安卓逆向从0到1学习总结
    DEX文件解析--7、类及其类数据解析(完结篇)
    网络设备配置--10、利用ACL配置访问控制
    网络设备配置--9、利用ppp协议实现点对点认证
    网络设备配置--8、利用ospf配置动态路由
  • 原文地址:https://www.cnblogs.com/song-/p/9620959.html
Copyright © 2011-2022 走看看