題意簡述
維護乙個 \(2*n\) 的網格圖的動態連通性
思路既然是動態連通性,那麼我們直接離線線段樹分治+可撤銷並查集
上面的做法太暴力了,我們考慮分析一些性質
注意到聯通的資訊是可以合併的,可以考慮使用線段樹維護
乙個想法是維護區間 左上/左下 到 右上/右下 的連通性
但這樣忽略了一種情況:
(1,1) - (1,2) (1,3) - (1,4)
| |
(2,1) - (2,2) - (2,3) - (2,4)
也就是說,我們可以通過詢問區間 左邊/右邊 部分實現行的改變
那麼再維護兩個資訊 \(l,r\) 表示區間 左上左下 , 右上右下 的連通性
合併區間和查詢時列舉中間點即可
#include #include using namespace std;
const int maxn = 1e5;
int n , v[ maxn + 5 ] , r[ 2 ][ maxn + 5 ];
struct node ;
struct segment_tree ;
for( int i = 0 ; i <= 1 ; i ++ )
for( int j = 0 ; j <= 1 ; j ++ )
for( int k = 0 ; k <= 1 ; k ++ )
s.chk[ i ][ j ] |= p.chk[ i ][ k ] & r[ k ][ md ] & q.chk[ k ][ j ];
s.l = p.l | ( p.chk[ 0 ][ 0 ] && p.chk[ 1 ][ 1 ] && r[ 0 ][ md ] & r[ 1 ][ md ] & q.l );
s.r = q.r | ( q.chk[ 0 ][ 0 ] && q.chk[ 1 ][ 1 ] && r[ 0 ][ md ] & r[ 1 ][ md ] & p.r );
return s;
}void build( int x , int l = 1 , int r = n )
build( ls , l , mid ); build( rs , mid + 1 , r );
}void update( int x , int pos , int l = 1 , int r = n )
update( ls , pos , l , mid ); update( rs , pos , mid + 1 , r );
tr[ x ] = merge( tr[ ls ] , tr[ rs ] , mid );
}node query( int x , int ql , int qr , int l = 1 , int r = n )
}tr;
char s[ 10 ];
int main( )
else v[ c1 ] = 1;
tr.update( 1 , c1 );
}if( s[ 0 ] == 'c' )
else v[ c1 ] = 0;
tr.update( 1 , c1 );
}if( s[ 0 ] == 'a' )
}return 0;
}
SHOI2008 堵塞的交通
有一篇超級棒的線段樹 大力分類討論的題解!戳我 可是我還是不會寫這個做法qwqwqwq 這裡提供線段樹分治的寫法。感覺比較不需要智商,就是跑的有點慢了。include include include include include include include include define max...
SHOI2008 堵塞的交通
這裡提供幾種不用腦子的演算法 當然是離線的 text 記下每條邊的刪除時間,用 text 維護最大生成樹,每次加進一條邊時,跟原來那條鏈上的做比較,刪除那條刪除時間最短的邊即可。線段樹分治 這個演算法將每條邊的加入和刪除時間加入到線段樹中,所以在遍歷到葉子節點時,那個時刻存在的邊都已經在並查集上了,...
SHOI2008 堵塞的交通
有一天,由於某種穿越現象作用,你來到了傳說中的小人國。小人國的布局非常奇特,整個國家的交通系統可 以被看成是乙個2行c列的矩形網格,網格上的每個點代表乙個城市,相鄰的城市之間有一條道路,所以總共有2c個 城市和3c 2條道路。小人國的交通狀況非常槽糕。有的時候由於交通堵塞,兩座城市之間的道路會變得不...