模型01預測值box-cox轉換為正態分佈評分
阿新 • • 發佈:2020-11-30
並查集,在一些有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