資料結構 樹上莫隊

2022-07-02 05:42:08 字數 1233 閱讀 1053

題意:給定一棵 \(n(2\leq n\leq 10^5)\) 個結點的樹,根結點為 \(1\) 號結點,每個結點有顏色 \(c(\leq c\leq 10^5)\) 。然後 \(m(1\leq m\leq 10^5)\) 次詢問,每次詢問給兩個引數 \((v,k)\) ,詢問 \(v\) 子樹內,頻次至少有 \(k\) 次的顏色有多少種。

題解:經典計數顏色的數量,使用莫隊演算法。不過這一次顏色的數量 \(k\) 不確定,也要作為乙個維度進行轉移。這一次查詢的並非樹鏈而是子樹,所以結點出棧的時候不需要刪除這個結點的資訊。對每個詢問給乙個區間 \([fst[v],lst[v]]\) 查詢頻次至少有 \(k\) 次的顏色有多少種。考慮帶修改的莫隊演算法,塊的大小為 \(\sqrt[3]\) ,總複雜度為 \(o(\sqrt[3])\) 。但是實測表明開 \(\sqrt[2]\) 更快,不知道原因是什麼,可能和這裡的區間並非任意指定有關(是dfs序的區間)。

namespace moalgorithmontree 

}struct node

} node[maxm];

ll ans[maxm];

int l, r, k;

ll curans;

int c[maxn], cnt[maxc], sum[maxn];

void add(int x)

void sub(int x)

void addk()

void subk()

void solve()

idt = 0;

dfs(1, 0);

block = (int)ceil(pow(n, 0.667));

for (int i = 1; i <= m; ++i)

sort(node + 1, node + 1 + m);

l = 1, r = 0, k = 0, curans = n, sum[0] = n;

for (int i = 1; i <= m; ++i)

for (int i = 1; i <= m; ++i)

printf("%lld\n", ans[i]);

}};

但是換一種思路,其實k沒有必要作為其中乙個維度,不過就不再維護curans,或者說,curans是乙個陣列,curans[i]表示頻次大於等於i的顏色數。考慮一種顏色頻次從cnt增加到cnt+1時,只會讓大於等於cnt+1的答案+1,對於大於等於cnt其實是沒有變化的。

這道題也可以樹上啟發式合併做。

樹上莫隊演算法

繼續回來寫部落格 記錄點有意思的題目什麼的。貌似寫過這個的沒多少人 所以我也記錄一點。首先序列上的莫隊大家都應該很熟悉了 那麼樹上的莫隊要怎麼搞呢?先來看個題目 spoj cot2 求樹上兩點間路徑上有多少個不同的點權。序列上的莫隊是把詢問按照左端點分塊了 可是樹上沒有左端點,怎麼辦呢?我們把樹分塊...

樹上莫隊演算法

樹上莫隊,顧名思義就是把莫隊搬到樹上。我們從一道題目入手 sdoi2018 原題識別 spoj count on a tree ii 題目意思很明確 給定乙個 n 個節點的樹,每個節點表示乙個整數,問 u 到 v 的路徑上有多少個不同的整數。像這種不帶修改數顏色的題首先想到的肯定是樹套樹莫隊,那麼如...

樹上莫隊演算法

樹上莫隊,顧名思義就是把莫隊搬到樹上。我們從一道題目入手 sdoi2018 原題識別 spoj count on a tree ii 題目意思很明確 給定乙個 n 個節點的樹,每個節點表示乙個整數,問 u 到 v 的路徑上有多少個不同的整數。像這種不帶修改數顏色的題首先想到的肯定是樹套樹莫隊,那麼如...