大意是一颗有根树,根节点为1,树上有两个操作,一个是对两个节点间的节点开根号,一个是询问两个节点间所有节点的权值和
开根号就是暴力对每个节点开根号(因为开根号能很快的接近1)
(树链剖分解决树上问题就是把它转化成线性表,然后再用一些数据结构维护一下就好了。所以说线性表的的增删查改才是重点)
ac代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace {
template <typename T> inline void read(T &x) {
x = 0; T f = 1;char s = getchar();
for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
for(; isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
x *= f;
}
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
const int N = 1e5+5;
struct edge{
int next, to;
}e[N*2];
struct Node{
int sum, l, r, ls, rs;
}a[N*2];
int n, m, cnt, head[N], v[N], rt;
int f[N], d[N], size[N], son[N], rk[N], top[N], id[N];
void add(int u, int v) {
e[++cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
void dfs1(int x) {
size[x] = 1, d[x] = d[f[x]] + 1;
for(int v, i = head[x]; i; i = e[i].next) {
if((v = e[i].to) != f[x]) {
f[v] = x, dfs1(v); size[x] += size[v];
if(size[son[x]] < size[v]) son[x] = v;
}
}
}
void dfs2(int x, int tp) {
top[x] = tp, id[x] = ++cnt, rk[cnt] = x;
if(son[x]) dfs2(son[x], tp);
for(int v, i = head[x]; i; i = e[i].next) {
if((v = e[i].to) != f[x] && v != son[x])
dfs2(v, v);
}
}
inline void pushup(int x) {
a[x].sum = a[a[x].ls].sum + a[a[x].rs].sum;
}
void build(int l, int r, int x) {
if(l == r) {
a[x].sum = v[rk[l]], a[x].l = a[x].r = l;
return ;
}
int mid = l + r >> 1;
a[x].ls = cnt++, a[x].rs = cnt++;
build(l, mid, a[x].ls);
build(mid + 1, r, a[x].rs);
a[x].l = l,a[x].r = r;
pushup(x);
}
inline len(int x) {
return a[x].r - a[x].l + 1;
}
void upd(int l ,int r, int x) {
if(a[x].l >= l && a[x].r <= r && a[x].sum == len(x)) {
return ;
}
if(a[x].l == a[x].r) {
a[x].sum = sqrt(a[x].sum);
return ;
}
int mid = a[x].l + a[x].r >> 1;
if(mid >= l) upd(l, r, a[x].ls);
if(mid < r) upd(l, r, a[x].rs);
pushup(x);
}
int qry(int l, int r, int x) {
if(a[x].l >= l && a[x].r <= r) return a[x].sum;
int mid = a[x].l + a[x].r >> 1, ret = 0;
if(mid >= l) ret += qry(l, r, a[x].ls);
if(mid < r) ret += qry(l , r, a[x].rs);
return ret;
}
inline int sum (int x, int y) {
int ret = 0;
while(top[x] != top[y]) {
if(d[top[x]] < d[top[y]]) swap(x, y);
ret += qry(id[top[x]], id[x], rt) ;
x = f[top[x]];
}
if(id[x] > id[y]) swap(x, y);
return ret + qry(id[x], id[y], rt);
}
void upd(int x, int y) {
while(top[x] != top[y]) {
if(d[top[x]] < d[top[y]]) swap(x, y);
upd(id[top[x]], id[x], rt);
x = f[top[x]];
}
if(id[x] > id[y]) swap(x, y);
upd(id[x], id[y], rt);
}
signed main() {
scanf("%lld%lld", &n, &m);
for(int i = 1; i <= n; i++) read(v[i]);
for(int x, y, i = 1; i < n; i++) {
read(x);read(y);
add(x, y);add(y, x);
}
cnt = 0, dfs1(1);dfs2(1,1);
cnt = 0, build(1,n,rt = cnt++);
for(int x, y, op, i = 1; i <= m; i++) {
read(op);read(x);read(y);
if(op == 0) upd(x,y);
else printf("%lld\n", sum(x, y));
}
}