[BZOJ]4034: [HAOI2015]树上操作
[HAOI2015]树上操作
题目大意:三个操作 1:a,b,c b节点权值+c 2:a,b,c 以b为根的子树节点权值全部+c 3:a,b 查询b到根路径的权值和。
题解:树链剖分
操作1 ,2是区间修改,3是区间和。
看题解都提示开long long 了,我也开了,可是整形相乘赋值给Long long时爆了。
简直要哭晕了。
代码:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 500005 #define LL long long using namespace std; int sumedge,cnt,n,m; int head[maxn],size[maxn],dad[maxn],deep[maxn],top[maxn]; int tpos[maxn],re[maxn],w[maxn]; struct Tree{ int l,r;LL sum,s; }tr[maxn<<2]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn<<1]; void read(int &x){ char ch=getchar();x=0;int f=1; for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; x=x*f; } void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x;dfs(v); size[x]+=size[v]; } } void dfs_(int x){ int s=0;tpos[x]=++cnt;re[cnt]=x; if(!top[x])top[x]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs_(v); } } void pushup(int rt){ tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; return; } void pushdown(int rt){ if(!tr[rt].s)return; tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s; tr[rt<<1].sum+=(LL)(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s; tr[rt<<1|1].sum+=(LL)(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s; tr[rt].s=0;return; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r){ tr[rt].sum=w[re[l]]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } void change(int rt,int l,int r,int ql,int qr,int p){ if(l>=ql&&r<=qr){ tr[rt].sum+=(LL)(r-l+1)*p; tr[rt].s+=p; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change(rt<<1,l,mid,ql,qr,p); if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p); pushup(rt); } LL query_sum(int rt,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr){ return tr[rt].sum; } pushdown(rt); int mid=(l+r)>>1;LL ans=0; if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr); if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr); return ans; } LL query(int x){ LL ret=0; for(;top[x]!=1;){ ret+=query_sum(1,1,n,tpos[top[x]],tpos[x]); x=dad[top[x]]; } ret+=query_sum(1,1,n,1,tpos[x]); return ret; } int main(){ read(n);read(m); for(int i=1;i<=n;i++)read(w[i]); for(int i=1;i<n;i++){ int x,y; read(x);read(y); add(x,y);add(y,x); } dfs(1);dfs_(1);build(1,1,n); for(int i=1;i<=m;i++){ int od,x,a; read(od);read(x); if(od==1){ read(a); change(1,1,n,tpos[x],tpos[x],a); }else if(od==2){ read(a); change(1,1,n,tpos[x],tpos[x]+size[x]-1,a); }else if(od==3){ printf("%lld\n",query(x)); } } return 0; }