1. 程式人生 > >【數軸染色+並查集路徑壓縮+加速】

【數軸染色+並查集路徑壓縮+加速】

pen 處理 維護 ret sed ram 分享 spl math

http://codevs.cn/problem/1191/

【思路】

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

如 3 3

  • fa[3]=2,操作一次

5 7,

  • fa[7]=fa[6]=fa[5]=4,操作三次

2 8:

  • fa[8]=fa[7],操作一次;
  • 由於5,6,7已經被合並到了4這個點,所以下一次直接跳到4;
  • fa[4]=3,操作一次;
  • fa[3]=2,直接調到2;
  • fa[2]=1,操作一次。

【Accepted】

技術分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<set>
 8 #include<queue>
 9 using namespace std;
10 const int maxn=2e5+3;
11 int fa[maxn]; 12 int n,m; 13 int find(int x) 14 { 15 return fa[x]==x?x:fa[x]=find(fa[x]); 16 } 17 void init() 18 { 19 for(int i=0;i<=n;i++) 20 { 21 fa[i]=i; 22 } 23 } 24 int main() 25 { 26 while(~scanf("%d%d",&n,&m)) 27 { 28 init(); 29 for
(int i=0;i<m;i++) 30 { 31 int x,y; 32 scanf("%d%d",&x,&y); 33 while(find(y)!=find(x-1)) 34 { 35 fa[find(y)]=fa[find(y)-1]; 36 n--; 37 } 38 cout<<n<<endl; 39 } 40 } 41 return 0; 42 }
View Code

【數軸染色+並查集路徑壓縮+加速】