BJOI2017 樹的難題 點分治,線段樹合併

2022-04-29 23:00:16 字數 1079 閱讀 1249

lg傳送門

點分治+線段樹合併。

我不會寫單調佇列,所以就寫了好寫的線段樹。

考慮對於每乙個分治中心,把出邊按顏色排序,這樣就能把顏色相同的子樹放在一起處理。用一棵動態開點線段樹維護顏色不同的子樹的資訊,另一棵動態開點線段樹維護顏色相同的子樹的資訊,同時按照題目要求更新答案。當子樹顏色變化時,就把第二棵線段樹合併到第一棵裡面去就好了。

**實現有點繁瑣,我調了很久。。。

#include#include#include#include#include#define r register

#define i inline

#define z first

#define y second

using namespace std;

const int s=200003,m=6000003,inf=0x3f3f3f3f;

char buf[1000000],*p1,*p2;

i char gc()

i int rd()

vector> g[s];

struct ta[m];

int c[s],s[s],t[s],h[s],v[s],n,m,e,l,u,u,r,o=-inf,a,b;

i int max(int x,int y)

i void add(int x,int y,int z)

i void ini()

int mrg(int k,int t)

void ins(int &k,int l,int r,int x,int v)

r int m=l+r>>1;

if(x<=m) ins(a[k].l,l,m,x,v);

else ins(a[k].r,m+1,r,x,v);

a[k].f=max(a[a[k].l].f,a[a[k].r].f);

}int qry(int k,int l,int r,int x,int y)

void dac(int x)

for(i=0;iif(!v[y=g[l][i].y])

dac(y);

}int main()

BJOI2017 樹的難題 點分治 線段樹

傳送門 傳送門 題意 給一棵樹,樹上有顏色,每種顏色有權值,定義一條路徑的權值為所有顏色相同段的權值之和,求長度在 l,r l,r l,r 中的路徑的最大權值。資料範圍 暴力過不了 顯然是個點分治 對於分治中心考慮過中心的路徑貢獻的答案 以下的 子樹 指根直接與分治中心相連的子樹 把分治中心作為根,...

BJOI2017 樹的難題

按照常規思路,選乙個點x作為分治中心,拼接x出發到子樹各點的路徑。對於拼接時兩段介面處 即x連出的那條邊,若沒有,設為0號邊 顏色為0,長度為0,到達0號兒子 顏色的影響,可以記錄每段的路徑權值 邊數以及該段的介面,將所有的路徑以介面顏色為第一關鍵字,介面編號為第二關鍵字排序。顯然,對於同一介面的路...

樹的點分治

codeforces 150e 通過點分治以及合併子樹檢查二分的答案 用深度從小到大的方式可以剪枝,達到nlog 2 n 的複雜度 不離散化常數巨大,離散化常數依然巨大 include include include include include define maxn 100005 define...