洛谷P3178 [HAOI2015]树上操作 (树链剖分)
题目链接:
https://www.luogu.com.cn/problem/P3178
思路:
树剖板子
代码:
#include <bits/stdc++.h> #define ls node<<1 #define rs node<<1|1 using namespace std; typedef long long ll; const int MAXN=2e5+5; ll n,m; ll head[MAXN],tot; struct node { ll to,nxt; }e[MAXN<<1]; void add(ll x,ll y) { e[tot].to=y;e[tot].nxt=head[x];head[x]=tot++; } void add_edge(ll x,ll y){add(x,y);add(y,x);} ll dep[MAXN],f[MAXN],sz[MAXN],son[MAXN]; void dfs(int u,int fa) { dep[u]=dep[fa]+1;sz[u]=1;f[u]=fa; for(int i=head[u];~i;i=e[i].nxt) { ll v=e[i].to; if(v!=fa) { dfs(v,u); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; } } } ll top[MAXN],id[MAXN],val[MAXN],a[MAXN],cnt; void dfs2(ll u,ll t) { top[u]=t;id[u]=++cnt;a[cnt]=val[u]; if(son[u]) dfs2(son[u],t); for(int i=head[u];~i;i=e[i].nxt) { ll v=e[i].to; if(v!=f[u]&&v!=son[u]) dfs2(v,v); } } ll tree[MAXN<<2],lazy[MAXN<<2]; void push_up(ll node) { tree[node]=tree[ls]+tree[rs]; } void build(ll node,ll l,ll r) { if(l==r){tree[node]=a[l];return;} ll mid=(l+r)>>1; build(ls,l,mid);build(rs,mid+1,r); push_up(node); } void push_down(ll node,ll l,ll r,ll mid) { if(lazy[node]) { lazy[ls]+=lazy[node];lazy[rs]+=lazy[node]; tree[ls]+=lazy[node]*(mid-l+1);tree[rs]+=lazy[node]*(r-mid); lazy[node]=0; } } void update(ll node,ll l,ll r,ll x,ll y,ll k) { if(l>=x&&r<=y) { lazy[node]+=k;tree[node]+=(r-l+1)*k;return; } ll mid=(l+r)>>1; push_down(node,l,r,mid); if(x<=mid) update(ls,l,mid,x,y,k); if(y>mid) update(rs,mid+1,r,x,y,k); push_up(node); } ll query(ll node,ll l,ll r,ll x,ll y) { if(l>=x&&r<=y) { //cout<<tree[node]<<endl; return tree[node]; } ll mid=(l+r)>>1; push_down(node,l,r,mid); ll ans=0; if(x<=mid) ans+=query(ls,l,mid,x,y); if(y>mid) ans+=query(rs,mid+1,r,x,y); return ans; } ll tree_sum(ll x,ll y) { ll fx=top[x],fy=top[y];ll ans=0; while(fx!=fy) { if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy); ans+=query(1,1,n,id[fx],id[x]); x=f[fx];fx=top[x]; } if(id[x]>id[y])swap(x,y); //cout<<id[x]<<" "<<id[y]<<endl; ans+=query(1,1,n,id[x],id[y]); return ans; } int main() { memset(head,-1,sizeof(head)); scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) { scanf("%lld",&val[i]); } for(int i=1;i<n;i++) { ll x,y;scanf("%lld%lld",&x,&y); add_edge(x,y); } dfs(1,0);dfs2(1,1);build(1,1,n); while(m--) { int op;scanf("%d",&op); ll x,y; if(op==1) { scanf("%lld%lld",&x,&y); update(1,1,n,id[x],id[x],y); } if(op==2) { scanf("%lld%lld",&x,&y); update(1,1,n,id[x],id[x]+sz[x]-1,y); } if(op==3) { scanf("%lld",&x); printf("%lld\n",tree_sum(1,x)); } } return 0; }