Description
Wells来到了一个充满美食的群岛!
这个世界是由N个岛屿构成,由N-1座桥将这N个岛屿连接起来,每个岛屿上只生产一种美食,每个岛屿上美食都是不同的,第i种美食会给Wells带来一个幸福度 wi ,当然不同的美食给Wells带来的幸福度可能是相同的。
作为一个曾经的吃货,对于美食还是非常挑剔的,Wells秉持中庸之道,只会吃带来幸福度在[a,b]中的美食而且每种只会吃一次(毕竟最近Wells的压力真的非常大,吃不下太多……),当然不同时候Wells所认定的a,b是不同的。
现在Wells需要游历美食群岛,Wells想知道如果这时候从u出发到达v,在当时给定的[a,b]下,他最多可以获得多少幸福度。
当然,美食群岛也是一个动态的变动系统,也会在某个时刻更改生产美食的种类,更新幸福度。
那么问题来了,Wells很懒,需要聪明的你回答他的每次询问。
Input
多组数据,对于每组数据:
第一行给定两个整数 n,m(1≤n,m≤10^5), 表示岛屿个数和Wells的询问个数.
第二行 c1,c2,…,cn(1≤ci≤10^7),表示第i个岛屿的美食带给Wells的幸福度
接下来n-1行,每行两个整数x,y(1≤x,y≤n),表明第x个岛屿与第y个岛屿之间有一座桥相连。
接下来m行,每行开始有一个字符表明询问或者修改信息
若以Q开头,代表是询问信息,Q后将紧跟4个数字 s,t,a,b(1≤s,t≤n;1≤a≤b≤10^7)表明出发城市,目标城市,Wells选定的幸福度的区间。
若以C开头,代表修改操作,C后紧跟两个数字 x,y(x≤n,;1≤y≤10^7),表示将第x个岛屿的美食幸福度改为y。
Output
对于每个Q询问,输出一行,表示从s->t路径上满足[a,b]限制情况下Wells最大能获得的幸福度。
Sample Input
5 3
1 2 1 3 2
1 2
2 4
3 1
2 5
Q 4 5 1 3
Q 1 1 1 1
Q 3 5 2 3
Sample Output
7
1
4
传送门:戳这里
题解:树上链的问题,首先想到用树剖,但这道题要求求出链上所有权值在[a,b]之间的权值和,因此需要用树套树,再加上权值的范围是1e7,因此还需要把权值离散一下
此题还可以用CDQ分治求解,解题报告:戳这里
#include<cstdio>
#include<string.h>
#include<iostream>
#include<assert.h>
#include<stack>
#include<queue>
#include<algorithm>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
typedef long long LL;
const int MX = 1e5 + 5;
const int inf = 0x3f3f3f3f;
struct Edge {
int v, nxt;
} E[MX * 2];
int head[MX], tot;
int top[MX], f[MX], dep[MX], sz[MX], son[MX], p[MX], fp[MX], totp;
void init() {
memset (head, -1, sizeof (head) );
tot = 0;
}
void add_edge (int u, int v) {
E[tot].v = v;
E[tot].nxt = head[u];
head[u] = tot++;
}
void dfs (int u, int fa, int deep) {
f[u] = fa; dep[u] = deep;
sz[u] = 1; son[u] = 0;
for (int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa) continue;
dfs (v, u, deep + 1);
sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
}
void rebuild (int u, int t) {
top[u] = t;
fp[totp] = u; p[u] = totp++;
if (son[u]) rebuild (son[u], t);
else return;
for (int i = head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if (v == f[u] || v == son[u]) continue;
rebuild (v, v);
}
}
void pre_solve (int n) {
totp = 1;
dfs (1, 0, 1);
rebuild (1, 1);
}
const int MXM = 2e7 + 5;
struct Tree {
int n, m;
vector <int> root;
int cnt;
LL sum[MXM];
int ls[MXM], rs[MXM];
void init (int _n, int _m) {
n = _n, m = _m;
cnt = 0;
root.clear();
root.resize (n + 1);
}
void update (int p, int v, int l, int r, int prt, int &rt) {
rt = ++cnt;
ls[rt] = ls[prt]; rs[rt] = rs[prt];
sum[rt] = sum[prt] + v;
if (l == r) return;
int m = (l + r) >> 1;
if (p <= m) update (p, v, l, m, ls[prt], ls[rt]);
else update (p, v, m + 1, r, rs[prt], rs[rt]);
}
LL query (int L, int R, int l, int r, int rt) {
if (L <= l && R >= r) return sum[rt];
int m = (l + r) >> 1; LL ret = 0;
if (L <= m) ret += query (L, R, l, m, ls[rt]);
if (R > m) ret += query (L, R, m + 1, r, rs[rt]);
return ret;
}
void Update (int x, int y, int v) {
for (int i = x; i <= n; i += i & -i) update (y, v, 1, m, root[i], root[i]);
}
LL pre_sum (int x, int l, int r) {
if (x > n) x = n;
LL ret = 0;
for (int i = x; i > 0; i -= i & -i)
ret += query (l, r, 1, m, root[i]);
return ret;
}
LL Query (int L, int R, int l, int r) {
return pre_sum (R, l, r) - pre_sum (L - 1, l, r);
}
} T;
struct Que {
int op, u, v, a, b, x, y;
} q[MX];
int h[MX * 4], rear;
int val[MX];
int main() {
int n, m;
char op[2]; int u, v, a, b, x, y;
//freopen ("in.txt", "r", stdin);
while (~scanf ("%d%d", &n, &m) ) {
rear = 0;
init();
for (int i = 1; i <= n; i++) scanf ("%d", &val[i]), h[++rear] = val[i];
for (int i = 1; i < n; i++) {
scanf ("%d%d", &u, &v);
add_edge (u, v);
add_edge (v, u);
}
pre_solve (n);
for (int i = 1; i <= m; i++) {
scanf ("%s", op);
if (op[0] == 'Q') {
scanf ("%d%d%d%d", &u, &v, &a, &b);
q[i] = (Que) {1, u, v, a, b, 0, 0};
h[++rear] = a;
h[++rear] = b;
} else {
scanf ("%d%d", &x, &y);
q[i] = (Que) {2, 0, 0, 0, 0, x, y};
h[++rear] = y;
}
}
sort (h + 1, h + rear + 1);
rear = unique (h + 1, h + rear + 1) - h - 1;
T.init (n, rear);
for (int i = 1; i <= n; i++) {
int pos = lower_bound (h + 1, h + rear + 1, val[fp[i]]) - h;
T.Update (i, pos, val[fp[i]]);
}
for (int i = 1; i <= m; i++) {
if (q[i].op == 1) {
u = q[i].u, v = q[i].v, a = q[i].a, b = q[i].b;
a = lower_bound (h + 1, h + rear + 1, a) - h;
b = lower_bound (h + 1, h + rear + 1, b) - h;
int f1 = top[u], f2 = top[v];
LL ans = 0;
while (f1 != f2) {
if (dep[f1] < dep[f2]) {
swap (u, v);
swap (f1, f2);
}
ans += T.Query (p[f1], p[u], a, b);
u = f[f1], f1 = top[u];
}
if (dep[u] > dep[v]) swap (u, v);
ans += T.Query (p[u], p[v], a, b);
printf ("%lld\n", ans);
} else {
x = q[i].x, y = q[i].y;
int p1 = lower_bound (h + 1, h + rear + 1, val[x]) - h;
int p2 = lower_bound (h + 1, h + rear + 1, y) - h;
T.Update (p[x], p1, -val[x]);
T.Update (p[x], p2, y);
val[x] = y;
}
}
}
return 0;
}