0
点赞
收藏
分享

微信扫一扫

HYSBZ 1036 树的统计Count


Description


  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身


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”的形式给出。 
对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。


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


Sample Output



4
1
2
2
10
6
5
6
5

16


树链剖分板子题。

#include<set>
#include<map>
#include<ctime>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define rep(i,j,k) for (int i = j; i <= k; i++)
#define per(i,j,k) for (int i = j; i >= k; i--)
#define loop(i,j,k) for (int i = j;i != -1; i = k[i])
#define lson x << 1, l, mid
#define rson x << 1 | 1, mid + 1, r
#define ff first
#define ss second
#define mp(i,j) make_pair(i,j)
#define pb push_back
#define pii pair<int,int>
#define inone(x) scanf("%d", &x)
#define intwo(x,y) scanf("%d%d", &x, &y)
using namespace std;
typedef long long LL;
const int low(int x) { return x&-x; }
const double eps = 1e-4;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int n, m, x, y;
int ft[N], nt[N], u[N], v[N], sz;
int fa[N], mx[N], ct[N], dep[N], top[N];
int F[N], G[N], cnt;
int f[N];
LL g[N];
char s[N];

void dfs(int x, int f)
{
ct[x] = 1; mx[x] = 0;
fa[x] = f; dep[x] = dep[f] + 1;
loop(i, ft[x], nt)
{
if (u[i] == f) continue;
dfs(u[i], x);
ct[x] += ct[u[i]];
mx[x] = ct[mx[x]] < ct[u[i]] ? u[i] : mx[x];
}
}

void Dfs(int x, int t)
{
top[x] = t ? x : top[fa[x]];
F[x] = ++cnt; G[cnt] = x;
if (mx[x]) Dfs(mx[x], 0);
loop(i, ft[x], nt)
{
if (u[i] == fa[x] || u[i] == mx[x]) continue;
Dfs(u[i], 1);
}
}

void update(int x)
{
f[x] = max(f[x << 1], f[x << 1 | 1]);
g[x] = g[x << 1] + g[x << 1 | 1];
}

void build(int x, int l, int r)
{
if (l == r) { g[x] = f[x] = v[G[l]]; return; }
int mid = l + r >> 1;
build(lson); build(rson); update(x);
}

void change(int x, int l, int r, int u, int v)
{
if (l == r) { f[x] = g[x] = v; return; }
int mid = l + r >> 1;
if (u <= mid) change(lson, u, v); else change(rson, u, v);
update(x);
}

int querymax(int x, int l, int r, int ll, int rr)
{
if (ll <= l&&r <= rr) return f[x];
int mid = l + r >> 1, ans = -INF;
if (ll <= mid) ans = max(ans, querymax(lson, ll, rr));
if (rr > mid) ans = max(ans, querymax(rson, ll, rr));
return ans;
}

LL querysum(int x, int l, int r, int ll, int rr)
{
if (ll <= l&&r <= rr) return g[x];
int mid = l + r >> 1; LL ans = 0;
if (ll <= mid) ans += querysum(lson, ll, rr);
if (rr > mid) ans += querysum(rson, ll, rr);
return ans;
}

void getlca(int x, int y, int a, int b)
{
int u = -INF; LL v = 0;
while (top[x] != top[y])
{
if (dep[top[x]] <= dep[top[y]]) swap(x, y);
u = max(u, querymax(1, 1, n, F[top[x]], F[x]));
v += querysum(1, 1, n, F[top[x]], F[x]);
x = fa[top[x]];
}
if (dep[x] >= dep[y]) swap(x, y);
u = max(u, querymax(1, 1, n, F[x], F[y]));
v += querysum(1, 1, n, F[x], F[y]);
printf("%lld\n", a*u + b*v);
}

int main()
{
while (inone(n) != EOF)
{
dep[0] = cnt = sz = 0;
rep(i, 1, n) ft[i] = -1;
rep(i, 1, n - 1)
{
intwo(x, y);
u[sz] = y; nt[sz] = ft[x]; ft[x] = sz++;
u[sz] = x; nt[sz] = ft[y]; ft[y] = sz++;
}
rep(i, 1, n) inone(v[i]);
dfs(1, 0); Dfs(1, 1);
build(1, 1, n);
inone(m);
rep(i, 1, m)
{
scanf("%s%d%d", s, &x, &y);
if (s[0] == 'C') change(1, 1, n, F[x], y);
if (s[0] == 'Q') getlca(x, y, s[1] == 'M', s[1] == 'S');
}
}
return 0;
}



举报

相关推荐

0 条评论