题目传送门:HDU - 3966 Aragorn's Story
题目大意:
存在一个树,树上每个节点为一个阵营,阵营中存在敌人,现在要进行以下操作
I C1 C2 K :将阵营C1到阵营C2路径经过的每个阵营的人数+k
D C1 C2 K :将阵营C1到阵营C2路径经过的每个阵营的人数-k
Q C:查询阵营C中的人数。
分析:
点权树链剖分,线段树维护区间和即可,单点查询,区间更新
代码:
#includeusing namespace std; typedef long long ll; #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 const int MAX=50009; struct Edge{ int next,to; }edge[MAX*2]; int head[MAX],cnt=0; int fa[MAX],deep[MAX],son[MAX],size[MAX],top[MAX],id[MAX],rk[MAX],tot; int n,m,p,a[MAX],u,v; char op[2]; int sum[MAX<<2],lazy[MAX<<2]; inline void add(int u,int v) { edge[cnt].to=v; edge[cnt].next=head[u]; head[u]=cnt++; } void dfs1(int u,int f,int d) { deep[u]=d; fa[u]=f; size[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=fa[u]) { dfs1(v,u,d+1); size[u]+=size[v]; if(son[u]==-1||size[son[u]]<size[v]) son[u]=v; } } } void dfstop(int u,int t) { top[u]=t; id[u]=tot++; rk[id[u]]=u; if(son[u]==-1)return; dfstop(son[u],t); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].to; if(v!=son[u]&&v!=fa[u]) dfstop(v,v); } } void PushUp(int rt) //维护区间和 { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Build(int l,int r,int rt) { if(l==r) { sum[rt]=a[rk[l]]; return; } int m=l+r>>1; Build(ls); Build(rs); PushUp(rt); } void PushDown(int ln,int rn,int rt) //lazy标记下传 { if(lazy[rt]) { lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; sum[rt<<1]+=lazy[rt]*ln; sum[rt<<1|1]+=lazy[rt]*rn; lazy[rt]=0; } } void Update(int L,int R,int val,int l,int r,int rt)//区间更新 { if(L<=l&&r<=R) { sum[rt]+=(r-l+1)*val; lazy[rt]+=val; return; } int m=l+r>>1; PushDown(m-l+1,r-m,rt); if(L<=m)Update(L,R,val,ls); if(R>m)Update(L,R,val,rs); PushUp(rt); } int Query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) return sum[rt]; int m=l+r>>1; int ans=0; PushDown(m-l+1,r-m,rt); if(L<=m)ans+=Query(L,R,ls); if(R>m)ans+=Query(L,R,rs); return ans; } void change(int x,int y,int v) //更新x->y路径的权值 { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]]) swap(x,y); Update(id[top[x]],id[x],v,1,tot,1); x=fa[top[x]]; } if(id[x]>id[y]) swap(x,y); Update(id[x],id[y],v,1,tot,1); } void init() { cnt=0; memset(head,-1,sizeof(head)); tot=1; memset(son,-1,sizeof(son)); memset(sum,0,sizeof(sum)); memset(lazy,0,sizeof(lazy)); memset(deep,0,sizeof(deep)); } int main() { while(~scanf("%d%d%d",&n,&m,&p)) { init(); for(int i=1;i<=n;i++)scanf("%d",&a[i]); while(m--) { scanf("%d%d",&u,&v); add(u,v);add(v,u); } dfs1(1,0,0);dfstop(1,1); Build(1,tot,1); while(p--) { int c1,c2,k; scanf("%s",op); if(op[0]=='I') { scanf("%d%d%d",&c1,&c2,&k); change(c1,c2,k); } if(op[0]=='D') { scanf("%d%d%d",&c1,&c2,&k); change(c1,c2,-k); } if(op[0]=='Q') { scanf("%d",&c1); printf("%d\n",Query(id[c1],id[c1],1,tot,1)); } } } return 0; }