第一版RE0 REcode
#include<bits/stdc++.h>
#define p1 (p << 1)
#define p2 ((p << 1) + 1)
using namespace std;
typedef long long ll;
inline ll read(){
ll x = 0, f = 1;char ch = getchar();
while(ch < '0'||ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x*f;
}
void write(ll x){
if(x < 0)putchar('-'),x = -x;
if(x > 9)write(x / 10);
putchar(x % 10 + '0');
}
const int N = 1e6 + 5;
ll pt[N], siz[N], depth[N], fa[N], son[N], top[N], dfn[N], rnk[N], tr[4 * N], lz[4 * N];//往dfn里塞进点,蹦出DFN,往rnk里塞DFN,蹦出点
ll n, m, from, to, cnt;
vector<int> G[N];
int Tfound(ll u,ll dep){
son[u] = -1, siz[son[u]] = 0, depth[u] = dep, siz[u] = 1;//重子节点初始化,大小初始化,深度设置
for(auto v:G[u]){
siz[u] += Tfound(v, dep + 1), fa[v] = u;//加上子树,设置父亲
if(son[u] == -1||siz[v] > siz[son[u]]) son[u] = v;//调整重子节点
}
return siz[u];
}
void dfs(ll u,ll t){
top[u] = t, dfn[u] = ++cnt, rnk[cnt] = u;
if(son[u] == -1) return;//叶子节点没有子节点
dfs(son[u], t);//优先遍历重子节点,以保证DFN有序
for(auto v:G[u]) if(v != son[u]) dfs(v, v);//没来过欸,是另一条链
}
void Build(int s,int t,int p){//对DFN建线段树
if(s == t){
tr[p] = pt[rnk[s]];
return;
}
int m = (s + t) >> 1;
Build(s, m, p1);
Build(m + 1, t, p2);
tr[p] = tr[p1] + tr[p2];
}
void PushDown(int p,int l,int r){
if(lz[p]){
int m = (l + r) >> 1;
tr[p1] += lz[p] * (m - l + 1), tr[p2] += lz[p] * (r - m);
lz[p1] += lz[p], lz[p2] += lz[p];
lz[p] = 1145141919810;
lz[p] = 0;
}
}
void RangeAdd(int l, int r,int s,int t,int p,int c){
if(s>=l && t<=r){
tr[p] += c * (t - s + 1), lz[p] += c;
return;
}
PushDown(p, s, t);
int m = (s + t) >> 1;
if(r <= m)RangeAdd(l, r, s, m, p1, c);
if(m < l) RangeAdd(l, r, m + 1, t, p2, c);
tr[p] = tr[p1] + tr[p2];
}
ll Query(int l,int r,int s,int t,int p){
if(s >= l && t <= r)return tr[p];
PushDown(p, s, t);
int m = (s + t) >> 1;
ll ret = 0;
if(l <= m)ret += Query(l, r, s, m, p1);
if(r > m) ret += Query(l, r, m + 1, t, p2);
return ret;
}
ll Q_line(int x,int y){
ll ret = 0;
while(top[x] != top[y]){
if(depth[top[x]] < depth[top[y]])swap(x,y);
ret += Query(dfn[top[x]], dfn[x], 1, n, 1);
x = fa[top[x]];
}
if(dfn[x] > dfn[y])swap(x, y);
ret += Query(dfn[x], dfn[y], 1, n, 1);
return ret;
}
int main(){
n = read(); m = read();
for(int i = 1; i <= n; i++) pt[i] = read();//点权
for(int i = 1; i < n; i++ ){//加边
from = read(); to = read();
G[from].push_back(to);
}
Tfound(1, 1);//一次DFS
dfs(1, 1); // 二次DFS
Build(1, n, 1);
while(m--){
int op, a, c;
op = read();a = read();
if(op == 1){
c = read();
RangeAdd(dfn[a], dfn[a], 1, n, 1, c);
}
else if(op == 2){
c = read();
RangeAdd(dfn[a], dfn[a] + siz[a] - 1, 1, n, 1, c);
}
else{
write(Q_line(a, 1));
puts("");
}
}
}
/*
BOTTOM = DFN + SIZ - 1
*/
第二版WA0,样例通过 WA0code
#include<bits/stdc++.h>
#define p1 (p << 1)
#define p2 ((p << 1) + 1)
using namespace std;
typedef long long ll;
inline ll read(){
ll x = 0, f = 1;char ch = getchar();
while(ch < '0'||ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
return x*f;
}
void write(ll x){
if(x < 0)putchar('-'),x = -x;
if(x > 9)write(x / 10);
putchar(x % 10 + '0');
}
const int N = 1e5 + 5;
ll pt[N], siz[N], depth[N], fa[N], son[N], top[N], dfn[N], rnk[N], tr[4 * N], lz[4 * N];//往dfn里塞进点,蹦出DFN,往rnk里塞DFN,蹦出点
ll n, m, from, to, cnt;
vector<int> G[N];
int Tfound(ll u,ll dep){
// printf("u = %d, dep = %d,fa[u] = %d\n",u,dep,fa[u]);
son[u] = -1, depth[u] = dep, siz[u] = 1;//重子节点初始化,大小初始化,深度设置
for(auto v:G[u]){
if(v == fa[u])continue;
fa[v] = u, siz[u] += Tfound(v, dep + 1);//加上子树,设置父亲
if(son[u] == -1||siz[v] > siz[son[u]]) son[u] = v;//调整重子节点
}
return siz[u];
}
void dfs(ll u,ll t){
top[u] = t, dfn[u] = ++cnt, rnk[cnt] = u;
if(son[u] == -1) return;//叶子节点没有子节点
dfs(son[u], t);//优先遍历重子节点,以保证DFN有序
for(auto v:G[u]) if(v != son[u] && v != fa[u]) dfs(v, v);//没来过欸,是另一条链
}
void Build(int s,int t,int p){//对DFN建线段树
if(s == t){
tr[p] = pt[rnk[s]];
return;
}
int m = (s + t) >> 1;
Build(s, m, p1);
Build(m + 1, t, p2);
tr[p] = tr[p1] + tr[p2];
}
void PushDown(int p,int l,int r){
if(lz[p]){
int m = (l + r) >> 1;
tr[p1] += lz[p] * (m - l + 1), tr[p2] += lz[p] * (r - m);
lz[p1] += lz[p], lz[p2] += lz[p];
lz[p] = 0;
}
}
void RangeAdd(int l, int r,int s,int t,int p,int c){
if(s >= l && t <= r){
tr[p] += c * (t - s + 1), lz[p] += c;
return;
}
PushDown(p, s, t);
int m = (s + t) >> 1;
if(r <= m)RangeAdd(l, r, s, m, p1, c);
if(m < l) RangeAdd(l, r, m + 1, t, p2, c);
tr[p] = tr[p1] + tr[p2];
}
ll Query(int l,int r,int s,int t,int p){
if(s >= l && t <= r)return tr[p];
PushDown(p, s, t);
int m = (s + t) >> 1;
ll ret = 0;
if(l <= m)ret += Query(l, r, s, m, p1);
if(r > m) ret += Query(l, r, m + 1, t, p2);
return ret;
}
ll Q_line(int x,int y){
ll ret = 0;
while(top[x] != top[y]){
if(depth[top[x]] < depth[top[y]])swap(x,y);
ret += Query(dfn[top[x]], dfn[x], 1, n, 1);
x = fa[top[x]];
}
if(dfn[x] > dfn[y])swap(x, y);
ret += Query(dfn[x], dfn[y], 1, n, 1);
return ret;
}
int main(){
freopen("P3178_1.in","r",stdin);
freopen("out.out","w",stdout);
fa[1] = 1;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) scanf("%lld",&pt[i]);//点权
for(int i = 1; i < n; i++ ){//加边
from = read(); to = read();
G[from].push_back(to);
G[to].push_back(from);
}
Tfound(1, 1);//一次DFS
dfs(1, 1); // 二次DFS
Build(1, n, 1);
while(m--){
int op, a, c;
op = read();a = read();
if(op == 1){
c = read();
RangeAdd(dfn[a], dfn[a], 1, n, 1, c);
}
else if(op == 2){
c = read();
RangeAdd(dfn[a], dfn[a] + siz[a] - 1, 1, n, 1, c);
}
else{
write(Q_line(a, 1));
puts("");
}
}
}
/*
BOTTOM = DFN + SIZ - 1
*/
希望可以有神犇调树剖
悬N关