1. 程式人生 > 實用技巧 >模型01預測值box-cox轉換為正態分佈評分

模型01預測值box-cox轉換為正態分佈評分

並查集,在一些有N個元素的集合應用問題中,我們通常是在開始時讓每個元素構成一個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查詢一個元素在哪個集合中。這一類問題近幾年來反覆出現在資訊學的國際國內賽題中,其特點是看似並不複雜,但資料量極大,若用正常的資料結構來描述的話,往往在空間上過大,計算機無法承受;即使在空間上勉強通過,執行的時間複雜度也極高,根本就不可能在比賽規定的執行時間(1~3秒)內計算出試題需要的結果,只能用並查集來描述。 (摘自百度)


關於並查集和路徑壓縮:

現在我們假定 f[i] 表示第 i 個人的老大是誰。

現在我們有甲,乙,丙三個人(分別用 a, b, c 表示)

假設甲和乙打架了,甲做了丙的小弟。則有 f[a]=b

後來甲打贏了丙

那麼丙就是甲的小弟了。有 f[c]=a

但是如果我們這樣表示,丙不能直接知道甲,容易自己人打自己人

所以,我們必須直接讓丙的大哥變成最大的老大。

定義函式 find

int find(int k){
    if(f[k]==k)return k;
    return find(f[k]);
}//find 函式可以直接找到最大的老大

f[c]=find(a);
//丙的老大是甲

這時,因為我們要路過他所有的上級,我們也可以順便使途中經過的人的大哥也變成老大。

//路徑壓縮
int find(int k){
    if(f[k]==k)return k;
    return f[k]=find(f[k]);
    /* 
        即:
        f[k]=find(f[k]);
        return f[k];
    */
}

f[c]=find(a);

簡直是太巧妙了!

而判定兩個人的老大是否相等,只需

if(find(a)==find(b))

就好了。

一些設定:

  • 一個人不能有兩個老大。
  • 當已經有老大的人臣服時,老大也將成為勝利的人的小弟。

AC程式碼:

#include<bits/stdc++.h>
using namespace std;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10
+ch-48;ch=getchar();} return x*f; } int n,m; int fa[5020000]; int find(int x) { if(x==fa[x]) return x; return fa[x]=find(fa[x]); } void ans(int x,int y) { if(find(x)==find(y)) printf("Y\n"); else printf("N\n"); } void hebing(int x,int y) { fa[find(x)]=find(y); } int main() { n=read(); m=read(); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=m;i++) { int opt,x,y; opt=read();x=read();y=read(); if(opt==1) { hebing(x,y); } else { ans(x,y); } } return 0; }

感謝巨神@ huangzirui