题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966
题意:给出一棵树,规定有三种操作:I操作,C1到C2路径上点的权值增加K
D操作,C1到C2路径上点的权值减少K
Q操作,查询C点的权值
思路:第一次练的树链剖分,套模板用线段树维护即可。
代码:
1 #include <iostream> 2 #include <string.h> 3 #include <algorithm> 4 #include <stdio.h> 5 #include <vector> 6 7 using namespace std; 8 //typedef long long ll; 9 const int MAX=50009; 10 11 int n,m,p,edge,x1,y1,z1,tim; 12 13 struct tr 14 { 15 int l,r; 16 int sum; 17 int lazy; 18 }tree[4*MAX]; 19 20 int a[MAX]; 21 int to[2*MAX],next1[2*MAX],head[MAX]; 22 23 //树链剖分模板 24 //dfs1 25 int dep[MAX];//节点的深度 26 int fa[MAX];//节点的父亲节点 27 int siz[MAX];//节点的儿子个数(子节点个数) 28 int son[MAX];//节点的重儿子 29 //dfs2 30 int top[MAX];//这条链的顶端节点 31 int tid[MAX];//按照链顺序的新编号 32 int rank1[MAX];//新编号对应的原编号 33 34 void addedge(int u,int v) 35 { 36 to[edge]=v,next1[edge]=head[u],head[u]=edge++; 37 to[edge]=u,next1[edge]=head[v],head[v]=edge++; 38 } 39 40 41 void dfs1(int u,int father,int d)//分出重儿子 42 { 43 dep[u]=d; 44 fa[u]=father; 45 siz[u]=1; 46 for(int i=head[u];~i;i=next1[i]) 47 { 48 int v=to[i]; 49 if(v!=father) 50 { 51 dfs1(v,u,d+1); 52 siz[u]+=siz[v]; 53 if(son[u]==-1||siz[v]>siz[son[u]]) 54 { 55 son[u]=v; 56 } 57 } 58 } 59 } 60 61 void dfs2(int u,int tp)//连点成链 62 { 63 top[u]=tp; 64 tid[u]=++tim; 65 rank1[tid[u]]=u; 66 if(son[u]==-1) return; 67 dfs2(son[u],tp); 68 for(int i=head[u];~i;i=next1[i]) 69 { 70 int v=to[i]; 71 if(v!=son[u]&&v!=fa[u]) 72 { 73 dfs2(v,v); 74 } 75 } 76 } 77 78 //线段树 79 void pushup(int x) 80 { 81 tree[x].sum=tree[x*2].sum+tree[x*2+1].sum; 82 //tree[x].sum=max(tree[x*2].sum,tree[x*2+1].sum); 83 return; 84 } 85 86 void pushdown(int x) 87 { 88 int nval=tree[x].lazy; 89 if(nval) 90 { 91 tree[x*2].sum+=(tree[x*2].r-tree[x*2].l+1)*nval; 92 tree[x*2+1].sum+=(tree[x*2+1].r-tree[x*2+1].l+1)*nval; 93 tree[x*2].lazy+=nval; 94 tree[x*2+1].lazy+=nval; 95 tree[x].lazy=0; 96 } 97 return; 98 } 99 100 void build(int l,int r,int x) 101 { 102 tree[x].l=l; 103 tree[x].r=r; 104 tree[x].sum=tree[x].lazy=0; 105 if(l==r) 106 { 107 tree[x].sum=a[rank1[l]]; 108 return; 109 } 110 int mid=(l+r)/2; 111 build(l,mid,x*2); 112 build(mid+1,r,x*2+1); 113 pushup(x); 114 return; 115 } 116 117 int query(int mb,int x) 118 { 119 int nl=tree[x].l,nr=tree[x].r; 120 if(nl==nr) 121 { 122 return tree[x].sum; 123 } 124 int mid=(nl+nr)/2; 125 int ans=0; 126 pushdown(x); 127 if (mb>mid)ans=query(mb,x*2+1); 128 else ans=query(mb,x*2); 129 pushup(x); 130 return ans; 131 } 132 133 void update(int l,int r,int val,int x) 134 { 135 int nl=tree[x].l,nr=tree[x].r; 136 if(l<=nl&&r>=nr) 137 { 138 tree[x].sum+=(nr-nl+1)*val; 139 tree[x].lazy+=val; 140 return; 141 } 142 pushdown(x); 143 int mid=(nl+nr)/2; 144 if(l<=mid)update(l,r,val,x*2); 145 if(r>mid)update(l,r,val,x*2+1); 146 pushup(x); 147 return; 148 } 149 150 void change(int x,int y,int val) 151 { 152 while(top[x]!=top[y]) 153 { 154 if(dep[top[x]]<dep[top[y]])swap(x,y); 155 update(tid[top[x]],tid[x],val,1); 156 x=fa[top[x]]; 157 } 158 if(dep[x]>dep[y])swap(x,y); 159 update(tid[x],tid[y],val,1); 160 return; 161 } 162 163 int main() 164 { 165 #ifndef ONLINE_JUDGE 166 freopen("in.txt","r",stdin); 167 #endif 168 char ch[5]; 169 while(~scanf("%d%d%d",&n,&m,&p)) 170 { 171 memset(head,-1,sizeof(head)); 172 memset(son,-1,sizeof(son)); 173 tim=0; 174 edge=0; 175 for(int i=1;i<=n;i++) 176 { 177 scanf("%d",&a[i]); 178 } 179 for(int i=1;i<=m;i++) 180 { 181 scanf("%d%d",&x1,&y1); 182 addedge(x1,y1); 183 184 } 185 dfs1(1,0,0); 186 dfs2(1,1); 187 build(1,n,1); 188 while(p--) 189 { 190 scanf("%s",ch); 191 if(ch[0]=='Q') 192 { 193 scanf("%d",&x1); 194 printf("%d\n",query(tid[x1],1)); 195 } 196 else 197 { 198 scanf("%d%d%d",&x1,&y1,&z1); 199 if(ch[0]=='D')z1=-z1; 200 change(x1,y1,z1); 201 } 202 } 203 } 204 return 0; 205 }