http://acm.hdu.edu.cn/showproblem.php?pid=6162php
题目大意:已知树上的每一个节点的值和节点之间的关系建成了一棵树,如今查询节点u到节点v的最短路径上的节点值在l到r之间的节点值得和node
解题思路:套用树链剖分的模板可以获得树上的链并把链上的节点进行了从新的定义(即在同一条链上的节点序列是连续的)。而后对于从新定义的节点进行建树。树有三个关键词,minn,maxx和sum。在查询时对从新定义的节点进行查询(即对u到v所通过的每条链分别进行查询)就能获得查询结果。c++
AC代码:数组
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <map> 5 #include <vector> 6 #include <bits/stdc++.h> 7 using namespace std; 8 const int MAXN = 100010; 9 struct Edge 10 { 11 int to,next; 12 } edge[MAXN*2]; 13 int head[MAXN],tot; 14 15 int top[MAXN];//top[v]表示v所在的重链的顶端节点 16 int fa[MAXN]; //父亲节点 17 int deep[MAXN];//深度 18 int num[MAXN];//num[v]表示以v为根的子树的节点数 19 int p[MAXN];//p[v]表示v与其父亲节点的连边在线段树中的位置 20 int fp[MAXN];//和p数组相反 21 int son[MAXN];//重儿子 22 int pos; 23 24 25 void init() 26 { 27 tot = 0; 28 memset(head,-1,sizeof(head)); 29 pos = 1;//序号实际上是从1开始? 30 memset(son,-1,sizeof(son)); 31 } 32 void addedge(int u,int v) 33 { 34 edge[tot].to = v; 35 edge[tot].next = head[u]; 36 head[u] = tot++; 37 } 38 void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son 39 { 40 deep[u] = d; 41 fa[u] = pre; 42 num[u] = 1; 43 for(int i = head[u]; i != -1; i = edge[i].next) 44 { 45 int v = edge[i].to; 46 //由于路径是双向的,因此不能等于父及诶单 47 if(v != pre) 48 { 49 //先递归地找到儿子节点的深度,父节点,子节点数目等信息 50 dfs1(v,u,d+1); 51 //更新u节点的儿子数目 52 num[u] += num[v]; 53 if(son[u] == -1 || num[v] > num[son[u]])//求出重儿子 54 son[u] = v; 55 } 56 } 57 } 58 59 //由于对于轻儿子来讲,top[u]=u,对于重儿子来讲,若是son[v]!=-1,那么top[v]=top[son[v]] 60 void getpos(int u,int sp) //第二遍dfs求出top和p 61 { 62 top[u] = sp; 63 //先找重儿子 64 if(son[u] != -1) 65 { 66 //把边的位置标记一下 67 p[u] = pos++; 68 //fp至关因而p的反函数? 69 fp[p[u]] = u; 70 //更新重儿子 71 getpos(son[u],sp); 72 } 73 //若是到了叶子节点 74 else 75 { 76 //再也不向下dfs 77 p[u] = pos++; 78 fp[p[u]] = u; 79 return; 80 } 81 //更新其余的节点 82 for(int i = head[u] ; i != -1; i = edge[i].next) 83 { 84 int v = edge[i].to; 85 if(v != son[u] && v != fa[u]) 86 getpos(v,v); 87 } 88 } 89 struct node 90 { 91 int maxx,minn; 92 long long sum; 93 }a[MAXN<<2]; 94 long long val[MAXN]; 95 int s,t,ut,dt; 96 int n,m; 97 void push_up(int k) 98 { 99 a[k].minn=min(a[k*2].minn,a[k*2+1].minn); 100 a[k].maxx=max(a[k*2].maxx,a[k*2+1].maxx); 101 a[k].sum=a[k*2].sum+a[k*2+1].sum; 102 } 103 void build(int l,int r,int k) 104 { 105 if(l==r) 106 { 107 a[k].maxx=a[k].minn=a[k].sum=val[fp[l]]; 108 return ; 109 } 110 int mid=(l+r)/2; 111 build(l,mid,k*2); 112 build(mid+1,r,k*2+1); 113 push_up(k); 114 } 115 long long query(int L,int R,int l,int r,int k) 116 { 117 int mid=(l+r)/2; 118 if(L<=l&&r<=R) 119 { 120 if(ut<=a[k].minn&&a[k].maxx<=dt) 121 { 122 return a[k].sum; 123 } 124 if(a[k].minn>dt||a[k].maxx<ut) 125 return 0LL; 126 return query(L,R,l,mid,k*2)+query(L,R,mid+1,r,k*2+1); 127 } 128 long long ans=0; 129 if(L<=mid) ans+=query(L,R,l,mid,k*2); 130 if(R>mid) ans+=query(L,R,mid+1,r,k*2+1); 131 return ans; 132 } 133 long long solve(int u,int v) 134 { 135 int f1=top[u]; 136 int f2=top[v]; 137 long long ans=0; 138 while(f1!=f2) 139 { 140 if(deep[f1]<deep[f2]) 141 { 142 swap(f1,f2); 143 swap(u,v); 144 } 145 ans+=query(p[f1],p[u],1,n,1); 146 u=fa[f1]; 147 f1=top[u]; 148 } 149 if(deep[v]<deep[u]) 150 { 151 swap(u,v); 152 } 153 ans+=query(p[u],p[v],1,n,1); 154 return ans; 155 } 156 int main() 157 { 158 while(~scanf("%d%d",&n,&m)) 159 { 160 for(int i=1;i<=n;i++) 161 scanf("%lld",&val[i]); 162 int x,y; 163 init(); 164 for(int i=1;i<n;i++) 165 { 166 scanf("%d%d",&x,&y); 167 addedge(x,y); 168 addedge(y,x); 169 } 170 dfs1(1,-1,0); 171 getpos(1,1); 172 build(1,n,1); 173 // for(int i=1;i<=n;i++) 174 // printf("%d = %d\n",i,fp[i]); 175 176 for(int i=0;i<m;i++) 177 { 178 scanf("%d%d%d%d",&s,&t,&ut,&dt); 179 val[i]=solve(s,t); 180 } 181 for(int i=0;i<m;i++) 182 { 183 if(i==0) 184 printf("%lld",val[i]); 185 else 186 printf(" %lld",val[i]); 187 } 188 printf("\n"); 189 } 190 return 0; 191 }