SPOJ COT2 樹上的莫隊演算法,樹上區間查詢

2021-07-04 15:51:17 字數 1209 閱讀 6617

題意:n個節點形成的一棵樹。每個節點有乙個值。m次查詢,求出(u,v)路徑上出現了多少個不同的數。

樹上的莫隊演算法,同樣將樹分成siz=sqrt(n)塊,然後離線操作。先對樹dfs一遍,每當子樹節點個數num>=siz,就將這num個分成一塊。讀取所有的查詢按左端點所在塊排序。

重點在於怎麼進行區間轉移,對路徑的lca特殊處理,參考部落格  

用倍增法求lca單次要用logn複雜度,要跑3200ms。有個地方可以優化,就是知道了所有的查詢,也就是事先知道了轉移路徑,可以用離線的方法求o(n)求出所有需要用到的lca,這個寫起來比較麻煩,不過可以優化到1800ns。**寫的比較挫。。。。

logn求lca:3200+ms

#include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;

const int maxn=4e4+10;

const int maxm=1e5+10;

int n,m, siz;

vectorg[maxn];

int a[maxn], b[maxn], ans[maxm];

int tot[maxn], in[maxn];

int fa[maxn][20], dep[maxn];

struct query

sort(q, q+m);

}int lca(int u, int v)

}return fa[u][0];

}void solve()

sort(q, q+m);

cnt=0; ltot=0;

memset(first, -1, sizeof(first));

add(1, q[0].l, cnt);

add(q[0].l, 1, cnt++);

add(1, q[0].r, cnt);

add(q[0].r, 1, cnt++);

add(q[0].r, q[0].l, cnt);

add(q[0].l, q[0].r, cnt++);

//add(q[0].r, q[0].l, cnt++);

for(int i=0; i>n>>m){

init();

solve();

for(int i=0; i

SPOJ COT2 樹上莫隊

以下路徑都不包含 lca lca 考慮當前知道路徑 u v u,v 的資訊,想要知道 t v t,v 的資訊,只需把 u t u,t 上的點狀態取反即可,那麼複雜度是和 u t u,t 的長度相關的。於是我們考慮把樹分塊,每當乙個點的子樹大小 n n就拎出來成為一塊。id i idi 表示i i 號...

SPOJ COT2 (樹上莫隊)

給你一棵大小為n nn的樹,每個點都有點權。現在有m mm個詢問,每個詢問給你乙個兩個數a,b a,ba,b,問你從點a aa到點b bb之間的路徑中不同的點權的個數。萬惡的spoj並沒有寫點權的資料範圍,害我我先re 此題需要離散化點權 求解帶有詢問的不同數的個數這類題,一看就相當莫隊 但是因為莫...

SPOJ COT2 (樹上莫隊)

給你一棵大小為 n 的樹,每個點都有點權。現在有 m 個詢問,每個詢問給你乙個兩個數 a,b 問你從點 a 到點 b 之間的路徑中不同的點權的個數。萬惡的spoj並沒有寫點權的資料範圍,害我我先re 此題需要離散化點權 求解帶有詢問的不同數的個數這類題,一看就相當莫隊 但是因為莫隊只能夠在乙個序列上...