SDOI2015 道路修建(線段樹維護連通性)

2022-03-17 00:08:00 字數 1204 閱讀 7303

這道題可以看做是[shoi2008]堵塞的交通的加強版,由於形同模擬不同人的寫法差別很大,強烈建議理解了原理之後自己獨立寫

給乙個\(2*m\)的網格圖,每次操作支援修改一條邊的權值,和查詢\([l,r]\)(含)的最小生成樹

如果做過上面那道題就很容易知道這道題是考(毒瘤的)線段樹

只需要維護8個標記(因寫法而異)

\(mst\):當前區間的最小生成樹

\(l,r\):當前區間的左右端點

\(lc,rc\):最小生成樹中,當前區間最左/右邊的豎線(顯然至少存在一條,否則上下不連通)

\(lmx,rmx\):最小生成樹中,最左/右邊的豎線左/右邊的所有橫線的最大值

\(mx\):該區間最長的橫線

合併兩個區間\([l,mid],[mid+1,r]\)時,加上中間兩條橫邊,顯然會和兩邊的豎線形成乙個環,從中刪掉一條邊即可:

刪掉橫邊,其它引數直接轉移

刪掉豎邊,分情況討論合併即可(這裡會用到\(mx\))

p.s. 不用擔心記錄的\(lmx,rmx,mx\)邊被刪掉的情況,證明很簡單,可以使用反證法,請獨立證明

#include#define n 60005

#define max(x,y) ((x)>(y)?(x):(y))

#define min(x,y) ((x)<(y)?(x):(y))

using namespace std;

int n,m,r[2][n],c[n];

struct node

int l,r,mst,lc,rc,lmx,rmx,mx;

}tr[n<<2];

template void read(t &x)

node pushup(node l,node r)

void update(int rt,int l,int r,int x)

int mid=(l+r)>>1;

if(x<=mid) update(rt<<1,l,mid,x);

else update(rt<<1|1,mid+1,r,x);

tr[rt]=pushup(tr[rt<<1],tr[rt<<1|1]);

}node query(int rt,int l,int r,int x,int y)

int main()

else

}else

}return 0;

}

SDOI2015 道路修建

傳送門 線段樹維護最小生成樹。兩個結點合併就是把兩個結點之間的兩條橫邊加上後形成乙個環,然後剪掉環上的最大值即可得到當前最小生成樹。不會證 於是現在只需要考慮怎麼找最大值。首先這個環一定是如下構成 兩邊是左節點的最右豎邊和右節點的最左豎邊,然後中間是所有的上下兩行橫邊。如下圖紅色部分。那麼發現維護每...

SDOI2015 道路修建

description 某國有2n個城市,這2n個城市構成了乙個2行n列的方格網。現在該國 有乙個旅遊發展計畫,這個計畫需要選定l r兩列 l r 修建若干條專用道路,使得這兩列之間 包括這兩列 的所有2 r l 1 個城市中每個城市可以只通過專用道路就可以到達這2 r l 1 個城市中的任何乙個城...

bzoj3995 SDOI2015 道路修建

題目鏈結 分析 曲神的題解 曲神表示想要結構體版本的 題解最後給出的就是結構體的 bzoj1018的高階版 一開始看到這道題 好像不是很難,用線段樹維護最小生成樹 update的時候直接判斷上下哪一條橫邊比較小,連線即可 然而一下就發現了bug 存在可能性連線點的上下兩條邊都需要連線 那我們就要深入...