HAOI2015 树上操作
题解:
线段树维护dfs序。
貌似是裸题。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 100050 #define ll long long inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,hed[N],cnt=0; struct EG { int to,nxt; }e[2*N]; void ae(int f,int t) { e[++cnt].to = t; e[cnt].nxt = hed[f]; hed[f] = cnt; } int a[N]; int tin[N],tout[N],tim,k[N<<1],K[N<<1]; void dfs(int u,int fa) { tin[u] = ++tim;k[tim]=1;K[tim]=a[u]; for(int j=hed[u];j;j=e[j].nxt) { int to = e[j].to; if(to==fa)continue; dfs(to,u); } tout[u]=++tim;k[tim]=-1;K[tim]=-a[u]; } struct segtree { ll v[N<<3],tag[N<<3],siz[N<<3]; void add(int u,ll d) { tag[u]+=d; v[u]+=d*siz[u]; } void pushdown(int u) { if(tag[u]) { add(u<<1,tag[u]); add(u<<1|1,tag[u]); tag[u]=0; } } void update(int u) { v[u] = v[u<<1]+v[u<<1|1]+siz[u]*tag[u]; } void build(int l,int r,int u) { if(l==r) { siz[u]=k[l]; v[u] = K[l]; tag[u]=0; return ; } int mid = (l+r)>>1; build(l,mid,u<<1); build(mid+1,r,u<<1|1); siz[u] = siz[u<<1]+siz[u<<1|1]; update(u); } void insert(int l,int r,int u,int ql,int qr,ll d) { if(l==ql&&r==qr) { add(u,d); return ; } pushdown(u); int mid = (l+r)>>1; if(qr<=mid)insert(l,mid,u<<1,ql,qr,d); else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,d); else insert(l,mid,u<<1,ql,mid,d),insert(mid+1,r,u<<1|1,mid+1,qr,d); update(u); } ll query(int l,int r,int u,int ql,int qr) { if(l==ql&&r==qr)return v[u]; pushdown(u); int mid = (l+r)>>1; if(qr<=mid)return query(l,mid,u<<1,ql,qr); else if(ql>mid)return query(mid+1,r,u<<1|1,ql,qr); else return query(l,mid,u<<1,ql,mid)+query(mid+1,r,u<<1|1,mid+1,qr); } }tr; int main() { n=rd(),m=rd(); for(int i=1;i<=n;i++) { a[i]=rd(); } for(int f,t,i=1;i<n;i++) { f=rd(),t=rd(); ae(f,t),ae(t,f); } dfs(1,0); tr.build(1,tim,1); for(int typ,x,y,i=1;i<=m;i++) { typ=rd(); if(typ==1) { x=rd(),y=rd(); tr.insert(1,tim,1,tin[x],tin[x],y); tr.insert(1,tim,1,tout[x],tout[x],y); }else if(typ==2) { x=rd(),y=rd(); tr.insert(1,tim,1,tin[x],tout[x],y); }else if(typ==3) { x=rd(); ll ans = tr.query(1,tim,1,1,tin[x]); printf("%lld\n",ans); }else break; } return 0; }