AngryBaconはシーケンスがとても好きで、シーケンスに関連するすべてのものが好きです。
AngryBaconの前に長さNのシーケンスがあり、各要素はMを超えない正の整数です。
AngryBaconはQマジックを使用します。マジックの内容が、Mを超えない正の整数a、bのペアであるたびに、aであるシーケンス内のすべての数値がbとして書き換えられることを意味します。
AngryBaconは、彼の最愛のシーケンスが最終的にどうなるかを知りたがっていました。
Inputの
最初の行には、3つの整数N、M、およびQが含まれています。意味は上記のとおりです。
2行目には、初期シーケンスを表すn個の整数が含まれています。次の行Qでは、各行に2つの整数a、bがあります。
出力
は、最終シーケンスの形状を示すN個の整数を含む1行を出力します。
サンプル
入力コピー55
3
1 2 3 4 5
3 1
4 3
15
出力52
5
35ヒント
[データ範囲]
データの20%の場合:1≤n、m、Q≤1000。
100のデータの場合:1≤n、m、Q≤1000000、1≤a、b、Ai≤M。
出典
ShiguangMiddle School 2017 Changle Summer Camp No. 7
意味: 理解できるはずです。
解決策: マージ検索の使用を考えるのは難しいことではありませんが、毎回新しいものに置き換える
ことを考えるのは難しいです。この
1-> 2
2-> 3
5-> 1のように、
かどうかを区別するのは簡単ではありません。 1は新しく生成されたものか元のもの
であるため、維持するために新しい配列が必要です。
/// a [x] = iは、数値xの最も早い点がiに現れることを意味します。
実際、ある数値が別の数値に変更されるたびに、それは全身に影響を与える種類の動きです。全身を動かすと、時間計算量が非常に大きくなるので、代表を見つけて、この代表だけを使ってこのタイプの数字を表します。このタイプの数字が変わる場合は、この数字を変えるだけです。
実際、その番号の最も早い位置を維持し、交換されるたびに最初の番号を交換することです。
高速読み取りを使用してください。scanfでタイムアウトしました。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e6+7;
int dis[maxn],vis[maxn];
int a[maxn];
int f(int x){
if(dis[x]==x) return x;
return dis[x]=f(dis[x]);
}
int read()
{
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {
if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int main(){
int n,m,p;
n=read();m=read();p=read();
///scanf("%lld%lld%lld",&n,&m,&p);
for(int i=1;i<=n;i++) dis[i]=i;
for(int i=1;i<=n;i++){
int x;
x=read();
///a[x]=i 表示x这个数出现最早点在i
///vis[i]=x 表示i点上放的是x
if(!a[x]) a[x]=i,vis[i]=x;///没动过 找到第一个节点
else dis[i]=f(a[x]);
///找到第一次出现的位置
}
while(p--){
int x,y;
x=read();y=read();
///找到第一次出现的地方
if(a[x]){
int tmp=a[x];
a[x]=0;
///找的这个,因为全部替换这个数就不会存在在序列中清零
///存在,就比较最靠前的是替换的靠前还是原本的,把他们连起来
if(a[y])dis[f(tmp)]=f(a[y]);
else a[y]=tmp,vis[tmp]=y;
///不存在b直接把a换成b不用比较 那么s数组放的值也会变化
}
}
for(int i=1;i<=n;i++){
printf("%d ",vis[f(i)]);///最后一次变成了什么
}
return 0;
}