51nod1515明辨是非

2021-08-08 18:45:16 字數 1730 閱讀 1723

1515

明辨是非

基準時間限制:1 秒 空間限制:131072 kb 分值: 160

難度:6級

給n組操作,每組操作形式為x y p。

當p為1時,如果第x變數和第y個變數可以相等,則輸出yes,並限制他們相等;否則輸出no,並忽略此次操作。

當p為0時,如果第x變數和第y個變數可以不相等,則輸出yes,並限制他們不相等 ;否則輸出no,並忽略此次操作。

input

輸入乙個數n表示操作的次數(n<=1*10^5)

接下來n行每行三個數x,y,p(x,y<=1*10^8,p=0 or 1)

output

對於n行操作,分別輸出n行yes或者no

input示例

31 2 1

1 3 1

2 3 0

output示例

yesyes

no

題解
思路很好的並查集的題。

以前做過一道程式自動分析的題,也是並查集,但那題對不相等的數沒有記錄,所以就是離散+排序+並查集就輕鬆秒掉。而這題對不相等的點也要進行記錄,而並查集只能對於乙個操作進行操作,所以還要乙個陣列記錄和它不相等的集合的父親,用set進行維護。
下面是具體操作。
把相等的變數存到乙個並查集裡,不相等的變數存到若干個集合中,s[i]集合存著所有與i不相等的變數所屬並查集的根。

每一次操作先獲得x, y的所屬並查集的根u, v.

當p == 0時,如果x和y在乙個並查集,也就是u == v,那麼就no,否則互相插入對方的集合。

當p == 1時,在u的集合裡查詢是不是有v,用內建的count函式,或者判斷find的返回值是否不等於s[u].end().

如果有,肯定是no,否則要進行集合合併,因為集合裡存的都是並查集的根,現在我要執行f[u] = v,就要把與u不相等的變數都加到v的集合裡,同時把與u不相等的變數所在的集合都插入v和刪除u(怎麼說著這麼彆扭,自行看**)(這塊我竟然和zrt想的一樣!)

為了降低開銷,肯定是要把小的集合並到大的集合裡,所以第一步進行了一次size()比較(不比較會mle)

因為x, y <= 10^8,所以不能開個一億的陣列儲存,觀察到操作次數最多隻會有100000次,也就是最多有200000個變數,那麼開個200005的陣列足夠,問題就是如何將乙個大數對應成乙個200000以內的數呢?有兩種方法:

第一種是先讀入所有變數,sort排序後,unique去重,要求離線。

最後就是輸出"yes"和"no"的時候不要用printf,會超時,用puts(這是一些經驗,要積累)。

#include#include#include#include#include#includeusing namespace std;

const int maxn=200010;

int fa[maxn];

sets[maxn];

mapm;

int find(int x)

int main()

puts("yes");

}else puts("yes");

} else

} }return 0;

}

51Nod 1515 明辨是非

給n組操作,每組操作形式為x y p。當p為1時,如果第x變數和第y個變數可以相等,則輸出yes,並限制他們相等 否則輸出no,並忽略此次操作。當p為0時,如果第x變數和第y個變數可以不相等,則輸出yes,並限制他們不相等 否則輸出no,並忽略此次操作。這是一道很經典的題目。如果只有強制相同集合的話...

51nod 1515 明辨是非

給n組操作,每組操作形式為x y p。當p為1時,如果第x變數和第y個變數可以相等,則輸出yes,並限制他們相等 否則輸出no,並忽略此次操作。當p為0時,如果第x變數和第y個變數可以不相等,則輸出yes,並限制他們不相等 否則輸出no,並忽略此次操作。輸入乙個數n表示操作的次數 n 1 10 5 ...

明辨是非 51Nod 1515

注意這題跟種類並查集不沾邊 因為a b b c推不出a c 對於每個集合u 把所有與u不等的集合v1 v2.都存入乙個vector 在合併u與v時 對其中vector元素較少的乙個進行遍歷 判斷是否包含另乙個集合 即啟發式合併 include include include include usin...