樹鏈剖分 線段樹 bzoj1036 樹的統計

2021-09-23 22:43:57 字數 2428 閱讀 3995

一棵樹上有n個節點,編號分別為1到n,每個節點都有乙個權值w。我們將以下面的形式來要求你對這棵樹完成一些操作: i. change u t : 把結點u的權值改為t ii. qmax u v: 詢問從點u到點v的路徑上的節點的最大權值 iii. qsum u v: 詢問從點u到點v的路徑上的節點的權值和 注意:從點u到點v的路徑上的節點包括u和v本身

輸入的第一行為乙個整數n,表示節點的個數。接下來n – 1行,每行2個整數a和b,表示節點a和節點b之間有一條邊相連。接下來n行,每行乙個整數,第i行的整數wi表示節點i的權值。接下來1行,為乙個整數q,表示操作的總數。接下來q行,每行乙個操作,以「change u t」或者「qmax u v」或者「qsum u v」的形式給出。 對於100%的資料,保證1<=n<=30000,0<=q<=200000;中途操作中保證每個節點的權值w在-30000到30000之間。

對於每個「qmax」或者「qsum」的操作,每行輸出乙個整數表示要求輸出的結果。

41 2

2 34 1

4 2 1 3

12qmax 3 4

qmax 3 3

qmax 3 2

qmax 2 3

qsum 3 4

qsum 2 1

change 1 5

qmax 3 4

change 3 6

qmax 3 4

qmax 2 4

qsum 3 441

22106

56516

樹鏈剖分:

需要進行兩次深搜,第一次dfs求出每個節點的siz,dep.

**如下:

void dfs1(int x)

}

dfs2要做的就是:將重鏈連線起來並順著重鏈重新給節點標號,這樣標出來的新序列就是線段樹里的區間了

void dfs2(int x, int top)

這樣樹鏈就剖分好了,要讓我們求x, y最短路勁上的和與極值,這個就由線段樹來處理

int solvesum(int x, int y)

if (pos[x] > pos[y]) swap(x, y);//x在y之前

sum += querysum(1, pos[x], pos[y]);

return sum;

}

完整**如下:

#include#include#include#include#include#define inf 0x7fffffff

#define n 30005

#define m 60005

using namespace std;

int n, q, cnt, sz;

int v[n], dep[n], siz[n], head[n], fa[n];

int pos[n], bl[n];

struct data e[m];

struct tree t[4*n];

void insert(int u, int v)

void init()

for (int i = 1;i <= n;i++) scanf("%d", &v[i]);

}void dfs1(int x)//求出siz dep fa

}void dfs2(int x, int chain)//將重邊連線成重鏈,按重鏈重新給節點標號

void build(int k, int l, int r)

void modify(int k, int x, int y)

if (x <= mid) modify(k << 1, x, y);

else modify(k << 1 | 1, x, y);

t[k].sum = t[k << 1].sum + t[k << 1 | 1].sum;

t[k].mx = max(t[k << 1].mx, t[k << 1 | 1].mx);

}int querysum(int k, int x, int y)

}int querymx(int k, int x, int y)

}int solvesum(int x, int y)

if (pos[x] > pos[y]) swap(x, y);//x在y之前

sum += querysum(1, pos[x], pos[y]);

return sum;

}int solvemx(int x, int y)

//退出迴圈時x,y在同一條重鏈上

if (pos[x] > pos[y]) swap(x, y);

mx = max(mx, querymx(1, pos[x], pos[y]));

return mx;

}int main()

return 0;

}

BZOJ 1036 樹的統計 Count 樹鏈剖分

題目大意 一棵樹上有n個節點,編號分別為1到n,每個節點都有乙個權值w。我們將以下面的形式來要求你對這棵樹完成一些操作 i.change u t 把結點u的權值改為t ii.qmax u v 詢問從點u到點v的路徑上的節點的最大權值 iii.qsum u v 詢問從點u到點v的路徑上的節點的權值和 ...

BZOJ 2243 樹鏈剖分 線段樹

include define n 101000 define frei freopen in.txt r stdin define freo freopen out.txt w stdout define mem a,b memset a,b,sizeof a define lson root 1 ...

BZOJ 4811 樹鏈剖分 線段樹

思路 感覺這題也可神了.還是我太弱 首先發現每一位不會互相影響,可以把每一位分開考慮,然後用樹鏈剖分或者lct維護這個樹 修改直接修改,詢問的時候算出來每一位填0,1經過這條鏈的變換之後得到的值 考慮貪心,從高往低,如果這一位填0可以得到1,那麼填0一定是最優的 否則如果可以填1,就把這一位填為1 ...