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;
    }
  • 相关阅读:
    eclipse历史版本下载地址
    注解@SuppressWarnings
    VB创建文件夹
    VB学习生成JavaBean
    C++下的强制转换类型
    Django扩展
    数据查询操作
    深入剖析C++多态、VPTR指针、虚函数表
    快速排序一步一步优化
    cookie与session
  • 原文地址:https://www.cnblogs.com/song-/p/9620959.html
Copyright © 2011-2022 走看看