推荐几个博客:https://blog.csdn.net/y990041769/article/details/40348013 树链剖分详解
https://blog.csdn.net/ACdreamers/article/details/10591443 树链剖分原理
1.(HDOJ3966)http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
分析:模板题(关于点权的树链剖分),先进行剖分,然后用树状数组去维护即可。区间修改,单点查询
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=50010; 6 struct Edge 7 { 8 int to,nxt; 9 }edge[maxn*2]; 10 int head[maxn],tot; 11 int top[maxn]; //top[v]表示v所在重链的顶端节点 12 int fa[maxn]; //父亲节点 13 int dep[maxn]; //深度 14 int num[maxn]; //num[v]表示以v为根的子树的节点数 15 int p[maxn]; //每个节点剖分后的新编号 16 int fp[maxn]; //当前节点在树状数组中的位置 17 int son[maxn]; //重儿子 18 int pos,n; 19 int bit[maxn]; 20 int a[maxn]; 21 22 void init() 23 { 24 tot=0; 25 memset(head,-1,sizeof(head)); 26 pos=1; //使用树状数组,编号从1开始 27 memset(son,-1,sizeof(son)); 28 } 29 30 void addedge(int u,int v) 31 { 32 edge[tot].to=v; 33 edge[tot].nxt=head[u]; 34 head[u]=tot++; 35 } 36 37 void dfs1(int u,int pre,int d) 38 { 39 dep[u]=d; 40 fa[u]=pre; 41 num[u]=1; 42 for ( int i=head[u];i!=-1;i=edge[i].nxt ) 43 { 44 int v=edge[i].to; 45 if ( v!=pre ) 46 { 47 dfs1(v,u,d+1); 48 num[u]+=num[v]; 49 if ( son[u]==-1 || num[v]>num[son[u]] ) son[u]=v; 50 } 51 } 52 } 53 54 void dfs2(int u,int sp) 55 { 56 top[u]=sp; 57 p[u]=pos++; 58 fp[p[u]]=u; 59 if ( son[u]==-1 ) return; 60 dfs2(son[u],sp); 61 for ( int i=head[u];i!=-1;i=edge[i].nxt ) 62 { 63 int v=edge[i].to; 64 if ( v!=son[u] && v!=fa[u] ) dfs2(v,v); 65 } 66 } 67 68 int lowbit(int x) 69 { 70 return x&(-x); 71 } 72 73 void add(int k,int val) 74 { 75 while ( k<=n ) 76 { 77 bit[k]+=val; 78 k+=lowbit(k); 79 } 80 } 81 82 int sum(int k) 83 { 84 int s=0; 85 while ( k ) 86 { 87 s+=bit[k]; 88 k-=lowbit(k); 89 } 90 return s; 91 } 92 93 void update(int u,int v,int val) //u->v的路径上点的值的改变 94 { 95 int f1=top[u],f2=top[v]; 96 int tmp=0; 97 while ( f1!=f2 ) 98 { 99 if ( dep[f1]<dep[f2] ) 100 { 101 swap(f1,f2); 102 swap(u,v); 103 } 104 add(p[f1],val); 105 add(p[u]+1,-val); 106 u=fa[f1]; 107 f1=top[u]; 108 } 109 if ( dep[u]>dep[v] ) swap(u,v); 110 add(p[u],val); 111 add(p[v]+1,-val); 112 } 113 114 int main() 115 { 116 int m,P,u,v,C1,C2,K; 117 char op[10]; 118 while ( scanf("%d%d%d",&n,&m,&P)!=EOF ) 119 { 120 init(); 121 for ( int i=1;i<=n;i++ ) scanf("%d",&a[i]); 122 while ( m-- ) 123 { 124 scanf("%d%d",&u,&v); 125 addedge(u,v); 126 addedge(v,u); 127 } 128 dfs1(1,0,0); 129 dfs2(1,1); 130 memset(bit,0,sizeof(bit)); 131 for ( int i=1;i<=n;i++ ) 132 { 133 add(p[i],a[i]); 134 add(p[i]+1,-a[i]); 135 } 136 while ( P-- ) 137 { 138 scanf("%s",op); 139 if ( op[0]=='Q' ) 140 { 141 scanf("%d",&u); 142 printf("%d\n",sum(p[u])); 143 } 144 else 145 { 146 scanf("%d%d%d",&C1,&C2,&K); 147 if ( op[0]=='D' ) K=-K; 148 update(C1,C2,K); 149 } 150 } 151 } 152 return 0; 153 }