P3178 [HAOI2015]树上操作
题解
树链剖分板子题
单点修改
区间修改
区间查询
于是我调了三天。。。
1.这题要开 long long
2.我之前单点修改写的有问题啊!!!
下面是正确的!!!
当然你也可以用区间修改代替单点修改
当我百度了之后,终于发现线段树单点修改写错了
安利博客吧线段树单点修改查询区间修改查询
代码
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<string> #include<cstring> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; inline ll read() { ll ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } const ll maxn=1e5+10; ll n,q,w[maxn]; ll head[maxn],to[maxn<<2],nxt[maxn<<2],cnt=0; inline void addedge(ll u,ll v) { to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt; to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt; } ll fa[maxn],size[maxn],son[maxn],dfn[maxn],que[maxn],dep[maxn],top[maxn],tim=0; ll laz[maxn<<2],sum[maxn<<2]; inline void dfs1(ll u,ll f) { fa[u]=f; size[u]=1; son[u]=0; for(ll i=head[u];i;i=nxt[i]){ ll v=to[i]; if(v==f) continue; dfs1(v,u); size[u]+=size[v]; if(size[v]>size[son[u]]) son[u]=v; } } inline void dfs2(ll u,ll f) { dfn[u]=++tim; que[tim]=u; dep[u]=dep[f]+1; top[u]=(son[f]==u?top[f]:u); if(son[u]) dfs2(son[u],u); for(ll i=head[u];i;i=nxt[i]){ ll v=to[i]; if(v==f||v==son[u]) continue; dfs2(v,u); } } inline void build(ll k,ll l,ll r) { if(l==r) //注意这里建树!!! { sum[k]=w[que[l]]; return ; } ll mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); sum[k]=sum[k<<1]+sum[k<<1|1]; } inline void modify1(ll k,ll l,ll r,ll p,ll v) //单点修改 { sum[k]+=v; if(l==r) return; ll mid=(l+r)>>1; if(p<=mid) modify1(k<<1,l,mid,p,v); if(mid<p) modify1(k<<1|1,mid+1,r,p,v); } inline void pushdown(ll k,ll l,ll r) { ll mid=(l+r)>>1; laz[k<<1]+=laz[k]; laz[k<<1|1]+=laz[k]; sum[k<<1]+=laz[k]*(mid-l+1); sum[k<<1|1]+=laz[k]*(r-mid); laz[k]=0; } inline void modify2(ll k,ll l,ll r,ll x,ll y,ll v) { if(x<=l&&r<=y){ laz[k]+=v; sum[k]+=(r-l+1)*v; return ; } if(laz[k]!=0) pushdown(k,l,r); ll mid=(l+r)>>1; if(x<=mid) modify2(k<<1,l,mid,x,y,v); if(mid<y) modify2(k<<1|1,mid+1,r,x,y,v); sum[k]=sum[k<<1]+sum[k<<1|1]; } ll querysum(ll k,ll l,ll r,ll x,ll y) { ll ans=0; if(y<l||r<x||l>r||x>y) return 0; if(x<=l&&r<=y) return sum[k]; if(laz[k]) pushdown(k,l,r); ll mid=(l+r)>>1; if(x<=mid) ans+=querysum(k<<1,l,mid,x,y); if(mid<y) ans+=querysum(k<<1|1,mid+1,r,x,y); return ans; } ll qussum(ll x,ll y) { ll ans=0; while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]]) swap(x,y); ans+=querysum(1,1,n,dfn[top[x]],dfn[x]); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); ans+=querysum(1,1,n,dfn[x],dfn[y]); return ans; } int main() { // freopen("test1.in","r",stdin); // freopen("yy.txt","w",stdout); n=read();q=read(); for(ll i=1;i<=n;i++) w[i]=read(); ll x,y,opr,a; for(ll i=1;i<n;i++) { x=read(),y=read(); addedge(x,y); } dfs1(1,0); dfs2(1,0); build(1,1,n); for(ll i=1;i<=q;i++) { opr=read(); if(opr==1){ x=read();a=read(); modify1(1,1,n,dfn[x],a); } if(opr==2){ x=read();a=read(); modify2(1,1,n,dfn[x],dfn[x]+size[x]-1,a); } if(opr==3){ x=read(); printf("%lld ",qussum(1,x)); } } return 0; }