点权树的模板题,另外发现树状数组也是可以区间更新的。。
注意在对链进行操作时方向不要搞错
线段树版本
#include<bits/stdc++.h> using namespace std; #define maxn 50005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct Edge{int to,next;}edge[maxn<<2]; int a[maxn],head[maxn],tot; int deep[maxn],fa[maxn],son[maxn],num[maxn]; int top[maxn],fp[maxn],p[maxn],pos; inline void addedge(int u,int v){edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;} void dfs1(int u,int pre,int dep){ fa[u]=pre;deep[u]=dep;num[u]=1; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v==pre) continue; dfs1(v,u,dep+1); num[u]+=num[v]; if(son[u]==-1 || num[son[u]]<num[v]) son[u]=v; } } void getpos(int u,int sp){ top[u]=sp;p[u]=pos++;fp[p[u]]=u; if(son[u]==-1) return; getpos(son[u],sp); for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(v!=fa[u] && v!=son[u]) getpos(v,v); } } int seg[maxn<<2]; void build(int l,int r,int rt){ seg[rt]=0; if(l==r) {seg[rt]=a[fp[l]];return;}//注意这里,线段树上坐标为i的点权值是第i个被访问到的点的权值 int m=l+r>>1; build(lson);build(rson); } inline void pushdown(int rt){ if(seg[rt]) { seg[rt<<1]+=seg[rt]; seg[rt<<1|1]+=seg[rt]; seg[rt]=0; } } void update(int L,int R,int c,int l,int r,int rt){ if(L<=l && R>=r){seg[rt]+=c;return;} pushdown(rt); int m=l+r>>1; if(L<=m) update(L,R,c,lson); if(R>m) update(L,R,c,rson); } int query(int pos,int l,int r,int rt){ if(l==r) return seg[rt]; pushdown(rt); int m=l+r>>1; if(pos<=m) return query(pos,lson); else return query(pos,rson); } void change(int u,int v,int c){ int f1=top[u],f2=top[v]; while(f1!=f2){ if(deep[f1]<deep[f2]){swap(u,v);swap(f1,f2);} update(p[f1],p[u],c,1,pos,1); u=fa[f1];f1=top[u]; } if(deep[u]>deep[v]) swap(u,v); update(p[u],p[v],c,1,pos,1); } void init(){ tot=pos=0;pos=1; memset(head,-1,sizeof head); memset(son,-1,sizeof son); } int main(){ int n,m,q,u,v,k; while(scanf("%d%d%d",&n,&m,&q)==3){ init(); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);} dfs1(1,0,0);getpos(1,1);build(1,pos,1); char op[2]; while(q--){ scanf("%s",op); if(op[0]=='I') {scanf("%d%d%d",&u,&v,&k);change(u,v,k);} else if(op[0]=='D'){scanf("%d%d%d",&u,&v,&k);change(u,v,-k);} else {scanf("%d",&u);printf("%d ",query(p[u],1,pos,1));} } } }
树状数组版本。。果然还是树状数组快一点啊
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define MAXN 50010 using namespace std; struct Edge{ int to, next; }edge[MAXN*2]; int head[MAXN], tot; int deep[MAXN]; int fa[MAXN]; int son[MAXN]; int p[MAXN]; int fp[MAXN]; int top[MAXN]; int num[MAXN]; int pos; int c[MAXN], n;//树状数组的 void init() { tot=0; memset(head,-1,sizeof(head)); pos=1;//树状数组,编号从1开始 memset(son,-1,sizeof(son)); memset(c,0,sizeof(c)); } void addedge(int u,int v) { edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++; } void dfs1(int u, int pre, int d){ deep[u] = d; fa[u] = pre; num[u] = 0; for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if (v != pre){//v不能是父节点 dfs1(v, u, d+1); num[u] += num[v]; if (son[u]==-1||num[v]>num[son[u]]) son[u] = v; } } } void getpos(int u, int sp){ top[u] = sp; p[u] = pos++; fp[p[u]] = u; if (son[u] == -1) return; getpos(son[u], sp); for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].to; if (v != fa[u] && v != son[u]) getpos(v, v); } } //树状数组 int lowbit(int i){ return i&(-i); } int sum(int i){ int s = 0; while(i<=n){ s += c[i]; i +=lowbit(i); } return s; } void add(int i, int val){ while(i>0){ c[i]+=val; i-=lowbit(i); } } void change(int u, int v, int val){ int f1 = top[u], f2 = top[v]; while(f1 != f2){ if (deep[f1]<deep[f2]){ swap(f1, f2); swap(u, v); } add(p[u], val);//树状数组的区间更新原理 add(p[f1]-1, -val);//这儿得减去一个东西 u = fa[f1]; f1 = top[u]; } if(deep[u]>deep[v]) swap(u,v);//默认u是v的祖先 add(p[u]-1, -val); add(p[v], val); } int a[MAXN]; int main(){ int M, P; while(~scanf("%d%d%d", &n, &M, &P)){ int u, v; int C1, C2, K; char op[2]; init(); for(int i = 1; i<=n; i++) scanf("%d", &a[i]); while(M--){ scanf("%d%d", &u, &v); addedge(u, v); addedge(v, u); } dfs1(1, 0, 0); getpos(1, 1); while(P--){ scanf("%s", op); if (op[0]=='Q'){ scanf("%d", &u); printf("%d ", sum(p[u])+a[u]); } else { scanf("%d%d%d", &C1, &C2, &K); if (op[0]=='D') K = -K; change(C1, C2, K); } } } }