線段樹分治

2022-05-07 09:57:11 字數 1888 閱讀 9717

day2模擬被完爆了w

來學一波線段樹分治 原來一直拿它口胡其實沒寫過。。

然鵝這個東西和線段樹的關係 就像點分治和點分樹一樣

並不用建出來 但遍歷順序是一致的

從上到下 從左兒子到右兒子 訪問「線段樹」的所有節點

每個節點表示乙個區間 當然維護的也是區間裡的值

這就要求我們維護的東西滿足區間加法

比如並查集啦線性基啦什麼的

先來一道例題

bzoj4025二分圖

當然先考慮邊的出現沒有時間限制的話我們怎麼做

對於一張無向圖隨便給它乙個根 那麼如果從這個根暴力染色的話

就是一黑一白一黑一白。。。顯然所有的環都要滿足長度為偶數

如果乙個連通分量滿足自己是乙個二分圖

現在用一條邊把它和另乙個連通分量連起來

那麼它們還是乙個二分圖(如果被連線的兩點是乙個顏色,把其中乙個圖的所有點顏色反過來就好了)

而且如果用兩個聯通分量中各自的任意乙個點來負責連線,顯然也是成立的,證明和上面一樣

所以連線那兩個根就好啦

所以不合法的情況出現 僅當兩點u, v已經聯通,這時又來的一條邊,讓他們變成了乙個奇環

而我們給了這個連通分量乙個根rt

如果u, v到根的路徑不重疊

那麼這兩點到根rt的距離dis[u] + dis[v]顯然是乙個偶數(因為加上新增的一條邊就是奇數了嘛

如果重疊呢?

發現重疊部分的貢獻2dis[lca(u, v)]也是乙個偶數 不對結果造成影響

所以我們維護並查集就好啦

首先把邊們按照出現時間排序

每次取乙個mid, 像線段樹分區間一樣把邊的時間區間分下去

如果到了某個節點發現此時有奇環 那麼這段時間的圖都不滿足二分圖性質

如果到了葉子節點還沒涼 那麼在這個時刻圖一定是二分圖

#include #include #include #include #include #include #include #include #define mp(x, y) make_pair(x, y)

using namespace std;

typedef pairpii;

const int n = 4e5 + 5;

int n, m, t;

struct line;

vectorvec[n << 2];

struct ufs

int find_f(int x)

int find_w(int x)

int merge(int x, int y, int w)

else

} void undo(int x)

}}ufs;

void segdiv(int l, int r, int rt)

if(!(wu ^ wv))

} else if(e.t <= mid) vec[ls].push_back(e);

else if(e.s > mid) vec[rs].push_back(e);

else vec[ls].push_back(e), vec[rs].push_back(e);

} if(l == r) printf("yes\n");

else segdiv(l, mid, ls), segdiv(mid + 1, r, rs);

ufs.undo(beg);

}int main());

} ufs.init();

segdiv(1, t, 1);

/* 輸入

每個邊插入

線段樹分治

考慮當前區間已經被覆蓋的

false no

true判斷葉子返回 /下放

redo

*/ return 0;

}

線段樹分治

動態圖聯通性 可離線 loj121 給你一張無向圖,你要支援如下操作 1 刪除一條邊 2 加入一條邊 3 查詢某兩個點對間是否聯通 離線做法 線段樹分治 口胡做法 把操作的順序當做時間。每條邊維護乙個存活區間,代表這條邊在這個時間區間裡面活著。對時間軸建立一顆線段樹,從線段樹根開始dfs。進入乙個子...

線段樹分治

首先,這裡的線段樹是狹義的線段樹。而線段樹分治是一種維護時間區間的資料結構,利用線段樹的分治性使時間複雜度為log loglo g級別。維護時間區間的資料結構有cdq分治 kd tree,那麼線段樹分治和它們的區別在 呢?其實,它就是用回退操作來實現可持久化,或者說是維護了操作會影響的時間區間。我們...

線段樹分治

這個演算法借助線段樹,然後事實上是通過遍歷線段樹進行分治。先用一種比較容易的方式來解釋吧。先回憶天天愛跑步一類的題目,大致就是在一棵樹上通過dfs,訪問到這個點的時候把這個點上的操作加入貢獻,離開的時候除去貢獻,然後就可以了。當我們發現乙個操作不能只用乙個點來表示,也即,兩個操作有交卻又不完全包含,...