[JSOI2008][BZOJ1036] 树的统计 - 树链剖分
Posted nishikino-curtis
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JSOI2008][BZOJ1036] 树的统计 - 树链剖分相关的知识,希望对你有一定的参考价值。
Description
一棵树上有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本身
Input & Output
Input
输入文件的第一行为一个整数n,表示节点的个数。
接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。
接下来一行n个整数,第i个整数wi表示节点i的权值。
接下来1行,为一个整数q,表示操作的总数。
接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample
Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 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 4
Output
4
1
2
2
10
6
5
6
5
16
Solution
资瓷单点修改,路径查询最大值,路径查询点权和,比较裸的树剖。
怕不是常数比较大只过了洛谷(逃
Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <string>
using std::min;
using std::max;
using std::swap;
using std::isdigit;
using std::memset;
using std::string;
using std::cin;
using std::cout;
using std::endl;
using std::ios;
const int maxn = 30005;
struct edge{
int to,nxt;
}e[maxn<<1];
struct node{
int w,mx,tag;
node()
{
mx = w = tag = 0;
}
}tr[maxn << 2];
int lnk[maxn],edgenum;
int top[maxn],size[maxn],dep[maxn],son[maxn],f[maxn],dfn[maxn],dfn2[maxn];
int cnt;
int w[maxn],v[maxn],n,m,q;
void add(int bgn,int end)
{
e[++edgenum].to = end;
e[edgenum].nxt = lnk[bgn];
lnk[bgn] = edgenum;
}
void dfs(int x,int fa,int d)
{
size[x] = 1;
f[x] = fa;
dep[x] = d;
for(int p = lnk[x]; p; p = e[p].nxt)
{
int y = e[p].to;
if(y == fa)continue;
dfs(y, x, d + 1);
size[x] += size[y];
if(size[y] > size[son[x]]) son[x] = y;
}
}
void dfs2(int x,int init)
{
dfn[x] = ++cnt;
w[cnt] = v[x];
top[x] = init;
if(!son[x])return;
dfs2(son[x],init);
for(int p = lnk[x]; p; p = e[p].nxt)
{
int y = e[p].to;
if(y == f[x]||y == son[x])continue;
dfs2(y,y);
}
}
void build(int cur,int l,int r)
{
if(l == r)
{
tr[cur].w = w[l];
tr[cur].mx = w[l];
return;
}
int mid = (l + r) >> 1;
build(cur<<1,l,mid);
build(cur<<1|1,mid + 1,r);
tr[cur].w = tr[cur<<1].w + tr[cur<<1|1].w;
tr[cur].mx = max(tr[cur<<1].mx,tr[cur<<1|1].mx);
}
int querys(int cur,int l,int r,int L,int R)
{
int res = 0;
if(L <= l && R >= r)
{
res += tr[cur].w;
return res;
}
int mid = (l+r)>>1;
if(L<=mid) res += querys(cur<<1,l,mid,L,R);
if(R>mid) res += querys(cur<<1|1,mid+1,r,L,R);
return res;
}
int queryx(int cur,int l,int r,int L,int R)
{
int res = -214748;
if(L <= l && R >= r)
return tr[cur].mx;
int mid = (l+r)>>1;
if(L<=mid) res = max(res, queryx(cur<<1,l,mid,L,R));
if(R>mid) res = max(res, queryx(cur<<1|1,mid+1,r,L,R));
return res;
}
void pupdate(int cur,int l,int r,int p,int c)
{
if(l == r)
{
tr[cur].w = c;
tr[cur].mx = c;
return;
}
else{
int mid = (l+r)>>1;
if(p <= mid)pupdate(cur<<1,l,mid,p,c);
else pupdate(cur<<1|1,mid+1,r,p,c);
tr[cur].w = tr[cur<<1].w + tr[cur<<1|1].w;
tr[cur].mx = max(tr[cur<<1].mx,tr[cur<<1|1].mx);
}
}
//---------------------------
int queryts(int x,int y)
{
int ans = 0;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])swap(x,y);
ans += querys(1,1,n,dfn[top[x]],dfn[x]);
x = f[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
ans += querys(1,1,n,dfn[x],dfn[y]);
return ans;
}
int querytx(int x,int y)
{
int ans = -214748;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])swap(x,y);
ans = max(ans, queryx(1,1,n,dfn[top[x]],dfn[x]));
x = f[top[x]];
}
if(dep[x] > dep[y])swap(x,y);
ans = max(ans, queryx(1,1,n,dfn[x],dfn[y]));
return ans;
}
int main()
{
ios::sync_with_stdio(false);
string s;
int x,y;
cin >> n;
for(int i = 1; i < n; ++i)
{
cin >> x >> y;
add(x,y);
add(y,x);
}
for(int i = 1; i <= n; ++i)
cin >> v[i];
dfs(1,0,1);
dfs2(1,1);
build(1,1,n);
cin >> q;
for(int i = 1; i <= q; ++i)
{
cin >> s;
if(s[0] == 'C')
{
cin >> x >> y;
pupdate(1,1,n,dfn[x],y);
}
else if(s[0] == 'Q' && s[1] == 'M')
{
cin >> x >> y;
cout << querytx(x,y) << endl;
}
else
{
cin >> x >> y;
cout << queryts(x,y) << endl;
}
}
return 0;
}
以上是关于[JSOI2008][BZOJ1036] 树的统计 - 树链剖分的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1036: [ZJOI2008]树的统计Count
bzoj 1036: [ZJOI2008]树的统计Count
bzoj 1036: [ZJOI2008]树的统计Count