【題目鏈接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1036
【題意】
【題解】
樹鏈剖分入門題;
每一條鏈維護(hù)一個線段樹就好;
uppest數(shù)組維護(hù)這條鏈的最頂端的元素;
一條鏈一條鏈的往上走;直到兩個點在同一條鏈里面了
balabala
【完整代碼】
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%lld",&x)
#define ref(x) scanf("%lf",&x)typedef pair<
int,
int> pii;
typedef pair<LL, LL> pll;
const int dx[
9] = {
0,
1,-
1,
0,
0,-
1,-
1,
1,
1 };
const int dy[
9] = {
0,
0,
0,-
1,
1,-
1,
1,-
1,
1 };
const double pi =
acos(-
1.0);
const int N =
3e4+
100;
const int INF =
3e4 +
200;
int n,fa[N],siz[N],dep[N],uppest[N],bh[N],cnt;
int v[N],sum[N<<
2],mx[N<<
2];
vector <int> G[N];
void in()
{rei(n);rep1(i,
1, n -
1){
int x, y;rei(x), rei(y);G[x].pb(y), G[y].pb(x);}rep1(i,
1, n)rei(v[i]);
}
void dfs1(
int x)
{
int len = G[x].size();siz[x] =
1;rep1(i,
0, len -
1){
int y = G[x][i];
if (y == fa[x])
continue;fa[y] = x;dep[y] = dep[x] +
1;dfs1(y);siz[x] += siz[y];}}
void dfs2(
int x,
int chain)
{
int len = G[x].size();
int k =
0;bh[x] = ++cnt;uppest[x] = chain;rep1(i,
0, len -
1){
int y = G[x][i];
if (dep[y]>dep[x] && siz[y] > siz[k])k = y;}
if (k ==
0)
return;dfs2(k, chain);rep1(i,
0, len -
1){
int y = G[x][i];
if (dep[y] > dep[x] && y != k)dfs2(y, y);}
}
void updata(
int pos,
int val,
int l,
int r,
int rt)
{
if (l == r){sum[rt] = mx[rt] = val;
return;}
int m = (l + r) >>
1;
if (pos <= m)updata(pos, val,lson);
elseupdata(pos, val,rson);sum[rt] = sum[rt <<
1] + sum[rt <<
1 |
1];mx[rt] = max(mx[rt <<
1], mx[rt <<
1 |
1]);
}
int query_max(
int L,
int R,
int l,
int r,
int rt)
{
if (L <= l && r <= R)
return mx[rt];
int m = (l + r) >>
1;
int temp1 = -INF;
if (L <= m)temp1 = max(temp1, query_max(L, R, lson));
if (m < R)temp1 = max(temp1, query_max(L, R, rson));
return temp1;
}
int get_max(
int u,
int v)
{
int t = -
3e4 -
100;
while (uppest[u] != uppest[v]){
if (dep[uppest[u]] < dep[uppest[v]])swap(u, v);t = max(t, query_max(bh[uppest[u]], bh[u],
1, n,
1));u = fa[uppest[u]];}
if (dep[u] < dep[v])swap(u, v);t = max(t, query_max(bh[v], bh[u],
1, n,
1));
return t;
}
int query_sum(
int L,
int R,
int l,
int r,
int rt)
{
if (L <= l && r <= R)
return sum[rt];
int m = (l + r) >>
1;
int temp =
0;
if (L <= m)temp += query_sum(L, R, lson);
if (m < R)temp += query_sum(L, R, rson);
return temp;
}
int get_sum(
int u,
int v)
{
int t =
0;
while (uppest[u] != uppest[v]){
if (dep[uppest[u]] < dep[uppest[v]])swap(u, v);t += query_sum(bh[uppest[u]], bh[u],
1, n,
1);u = fa[uppest[u]];}
if (dep[u] < dep[v])swap(u, v);t+=query_sum(bh[v], bh[u],
1, n,
1);
return t;
}
void get_ans()
{rep1(i,
1, n)updata(bh[i], v[i],
1, n,
1);
int q;rei(q);
char s[
8];rep1(i,
1, q){
scanf(
"%s", s);
if (s[
0] ==
'C'){
int u, t;rei(u), rei(t);updata(bh[u], t,
1, n,
1);}
else{
int u, v;rei(u), rei(v);
if (s[
1] ==
'M')
printf(
"%d\n", get_max(u, v));
elseprintf(
"%d\n", get_sum(u, v));}}
}
int main()
{in();dfs1(
1);dfs2(
1,
1);get_ans();
return 0;
}
轉(zhuǎn)載于:https://www.cnblogs.com/AWCXV/p/7626528.html
總結(jié)
以上是生活随笔為你收集整理的【BZOJ 1036】[ZJOI2008]树的统计Count的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。