1. 程式人生 > >【codevs1191】數軸染色 並查集

【codevs1191】數軸染色 並查集

題目描述 Description

在一條數軸上有N個點,分別是1~N。一開始所有的點都被染成黑色。接著
我們進行M次操作,第i次操作將[Li,Ri]這些點染成白色。請輸出每個操作執行後
剩餘黑色點的個數。

輸入描述 Input Description

輸入一行為N和M。下面M行每行兩個數Li、Ri

輸出描述 Output Description

輸出M行,為每次操作後剩餘黑色點的個數。

樣例輸入 Sample Input

10 3
3 3
5 7
2 8

樣例輸出 Sample Output

9
6
3

資料範圍及提示 Data Size & Hint

資料限制
對30%的資料有1<=N<=2000,1<=M<=2000
對100%資料有1<=Li<=Ri<=N<=200000,1<=M<=200000

一眼線段樹,雖然能過,不過太傻X了233

每次我們摧毀了一個區間,下一次如果還要摧毀這個區間或者它的子區間的話,我們就不用處理了。這樣我們可以把每一個區間抽象成一個點,用並查集來維護。合併時將[L,R]區間全部合併,然後n–。這樣每個點只會被合併一次,複雜度O(nα(n))
,跑得很快。

程式碼:

#include<cstdio>
#include<cstring> 
#include<iostream>
#include<algorithm> using namespace std; int fa[200010]; int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=0;i<=n;i++) fa[i]=i; while(m--) { int x,y; scanf("%d%d",&x,&y); while
(find(y)!=find(x-1)) fa[find(y)]=fa[find(y)-1],n--; printf("%d\n",n); } return 0; } /* g++ codevs1191.cpp -o codevs1191.exe -Wall */