一棵樹上有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 ...