题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
/* 要手动扩栈。 */ #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<iostream> #include<cstring> #define N 100010 using namespace std; int a[N],head[N],fa[N],son[N],dep[N],top[N],pos[N],sum[N*4],tag[N*4],n,m,p,sz; struct node{ int to,pre; };node e[N*2]; void add(int i,int x,int y){ e[i].to=y; e[i].pre=head[x]; head[x]=i; } void dfs1(int x){ son[x]=1; for(int i=head[x];i;i=e[i].pre){ int v=e[i].to; if(fa[x]==v) continue; fa[v]=x;dep[v]=dep[x]+1; dfs1(v); son[x]+=son[v]; } } void dfs2(int x,int chain){ ++sz;pos[x]=sz;top[x]=chain;int k=0,maxn=0; for(int i=head[x];i;i=e[i].pre) if(fa[x]!=e[i].to&&son[e[i].to]>maxn){ maxn=son[e[i].to]; k=e[i].to; } if(!k)return; dfs2(k,chain); for(int i=head[x];i;i=e[i].pre) if(e[i].to!=fa[x]&&e[i].to!=k) dfs2(e[i].to,e[i].to); } void pushup(int k){ sum[k]=sum[k*2]+sum[k*2+1]; } void pushdown(int k,int l,int r){ if(!tag[k]) return; int mid=l+r>>1; tag[k*2]+=tag[k]; tag[k*2+1]+=tag[k]; sum[k*2]+=tag[k]*(l-mid+1); sum[k*2+1]+=tag[k]*(r-mid); tag[k]=0; } void change(int l,int r,int k,int x,int y,int v){ if(l>=x&&r<=y){ tag[k]+=v; sum[k]+=(l-r+1)*v; return; } pushdown(k,l,r); int mid=l+r>>1; if(x<=mid) change(l,mid,k*2,x,y,v); if(y>mid) change(mid+1,r,k*2+1,x,y,v); pushup(k); } int query(int l,int r,int k,int pos){ if(l==r)return sum[k]; pushdown(k,l,r); int mid=l+r>>1; if(pos<=mid) return query(l,mid,k*2,pos); else return query(mid+1,r,k*2+1,pos); } void xiugai(int x,int y,int v){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); change(1,n,1,pos[top[x]],pos[x],v); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); change(1,n,1,pos[x],pos[y],v); } void work(){ for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++){ int x,y;scanf("%d%d",&x,&y); add(i*2-1,x,y);add(i*2,y,x); } dfs1(1);dfs2(1,1); for(int i=1;i<=n;i++)change(1,n,1,pos[i],pos[i],a[i]); char opt[10]; for(int i=1;i<=p;i++){ int x,y,v; scanf("%s",opt); if(opt[0]=='I'){ scanf("%d%d%d",&x,&y,&v); xiugai(x,y,v); } else if(opt[0]=='D'){ scanf("%d%d%d",&x,&y,&v); xiugai(x,y,-v); } else{ scanf("%d",&x); printf("%d\n",query(1,n,1,pos[x])); } } } int main(){while(scanf("%d%d%d",&n,&m,&p)!=EOF){ memset(head,0,sizeof(head)); memset(fa,0,sizeof(fa)); memset(son,0,sizeof(son)); memset(dep,0,sizeof(dep)); memset(top,0,sizeof(top)); memset(pos,0,sizeof(pos)); memset(sum,0,sizeof(sum)); memset(tag,0,sizeof(tag)); sz=0; work(); } return 0; }