• $Luogu$ $P1196$ $[NOI2002]$ 银河英雄传说


    链接

    背景

    (CCF) (NOI) (2002) (T1)(Luogu) (P1196/Vijos1443)

    题意

    给出 (30000) 艘战舰排成一行(从 (1)(30000) 编号),每艘独占一列。给出 (T) 条指令,形如 (M x y)(C x y) ,前一个表示第 (x) 号战舰所在的一列战舰整体平移到第 (y) 号战舰所在的一列战舰的后方,后一个表示查询第 (x) 号战舰和第 (y) 号战舰是否在同一列,若是的话还要查询两艘战舰之间隔着几艘战舰。

    解法

    考虑把每个战舰当做一个集合,用并查集维护当前战舰所在的集合的首个元素。当然,仅仅这样是不够的。由于要查询两艘战舰之间隔着几艘战舰,考虑维护每艘战舰 (x) 到首个元素(列首)的距离 (d_x) 。对于一个 (M) 操作,相当于是把 (x) 的代表元素作为 (y) 所在集合的一个节点,于是向 (y) 的代表元素合并 (x) 的代表元素即可。
    考虑合并的过程怎么更新 (d_x) 。求 (d_x) 的过程就是把它到根节点之间的所有边权求个和。于是魔改一下查询代表元素的函数即可。合并完之后考虑 (d_x) 已经被更新了,新的值是 (y) 所在集合的总战舰数,于是还要记一个 (siz_x) 表示节点 (x) 所在集合的元素数。也要动态维护。
    然后是 (C) 操作。显然直接查询 (x) 的代表元素和 (y) 的代表元素是否相同即可判定是否在同一列。然后两艘战舰之间隔着的战舰数就是 (left| d_x-d_y ight| -1) ,即两点到代表元素的距离之差减去一个元素的值。

    (trick)

    为每个节点 (i) 安排一个权值 (d_i) 用来回答询问或者判定合法性。注意 (d) 数组的维护方法(先递归找代表再累加权值)。

    代码

    $View$ $Code$
    
    //省略头文件
    using namespace std;
    inline int read()
    {
    	int ret=0,f=1;
    	char ch=getchar();
    	while(ch>'9'||ch<'0')
    	{
    		if(ch=='-')
    			f=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		ret=(ret<<1)+(ret<<3)+ch-'0';
    		ch=getchar();
    	}
    	return ret*f;
    }
    int T,x,y,fa[30005],d[30005],siz[30005];
    char op;
    int get(int x)
    {
    	if(x==fa[x])
    		return x;
    	int rt=get(fa[x]);
    	d[x]+=d[fa[x]];
    	return fa[x]=rt;
    }
    int main()
    {
    	T=read();
    	for(register int i=1;i<=30000;i++)
    	{
    		fa[i]=i;
    		siz[i]=1;
    	}
    	while(T--)
    	{
    		scanf("%c",&op);
    		x=read();
    		y=read();
    		if(op=='C')
    		{
    			int fx=get(x),fy=get(y);
    			if(fx!=fy)
    				printf("-1
    ");
    			else
    				printf("%d
    ",abs(d[x]-d[y])-1);
    		}
    		else
    		{
    			int fx=get(x),fy=get(y);
    			fa[fx]=fy;
    			d[fx]=siz[fy];
    			siz[fy]+=siz[fx];
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Haskell 差点儿无痛苦上手指南
    蛋疼的Apple IOS Push通知协议
    css概述
    数据挖掘十大经典算法
    序员工作究竟能干多久?程序猿的前途怎样?
    怎样将程序猿写出来的程序打包成安装包(最简单的)
    Denny Zhang:一辈子做一个自由职业者
    自己动手写操作系统--个人实践
    结构体数组
    英雄会挑战失败求原因
  • 原文地址:https://www.cnblogs.com/Peter0701/p/11808785.html
Copyright © 2020-2023  润新知