题意:
已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点u到节点v的最短路径上的节点值在l到r之间的节点值的和。
思路:
用树链剖分将树映射到线段树上,线段树上维护3个值,max,min和sum即可。
接下来就是一个简单的线段树上的查询。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 const int INF = 0x3f3f3f3f; 14 const int maxn=1e5+5; 15 16 int n, m, pos; 17 int s, e, a, b; 18 int val[maxn],fa[maxn],son[maxn],dep[maxn],num[maxn],top[maxn],p[maxn],fp[maxn]; 19 ll ans[maxn]; 20 vector<int> G[maxn]; 21 22 struct node 23 { 24 int l, r; 25 ll mx,mi,sum; 26 }t[maxn<<2]; 27 28 void dfs(int u, int pre, int d) 29 { 30 dep[u]=d; 31 son[u]=-1; 32 num[u]=1; 33 fa[u]=pre; 34 for(int i=0;i<G[u].size();i++) 35 { 36 int v=G[u][i]; 37 if(v==pre) continue; 38 dfs(v,u,d+1); 39 num[u]+=num[v]; 40 if(son[u]==-1 || num[son[u]]<num[v]) 41 son[u]=v; 42 } 43 } 44 45 void getpos(int u, int sp) 46 { 47 top[u]=sp; 48 if(son[u]!=-1) 49 { 50 p[u]=pos++; 51 fp[p[u]]=u; 52 getpos(son[u],sp); 53 } 54 else 55 { 56 p[u]=pos++; 57 fp[p[u]]=u; 58 return; 59 } 60 for(int i=0;i<G[u].size();i++) 61 { 62 int v=G[u][i]; 63 if(son[u]==v || v==fa[u]) continue; 64 getpos(v,v); 65 } 66 } 67 68 void PushUp(int o) 69 { 70 t[o].mx=max(t[o<<1].mx,t[o<<1|1].mx); 71 t[o].mi=min(t[o<<1].mi,t[o<<1|1].mi); 72 t[o].sum=t[o<<1].sum+t[o<<1|1].sum; 73 } 74 75 void build(int l, int r, int o) 76 { 77 t[o].l=l; 78 t[o].r=r; 79 if(l==r) 80 { 81 t[o].mx=t[o].mi=t[o].sum=val[fp[l]]; 82 return; 83 } 84 int mid=(l+r)>>1; 85 build(l,mid,o<<1); 86 build(mid+1,r,o<<1|1); 87 PushUp(o); 88 } 89 90 ll query(int ql, int qr, int l, int r, int o) 91 { 92 int mid=(l+r)>>1; 93 if(ql<=l && qr>=r) 94 { 95 if(t[o].mx<a || t[o].mi>b) return 0; 96 if(t[o].mi>=a && t[o].mx<=b) return t[o].sum; 97 return query(ql,qr,l,mid,o<<1)+query(ql,qr,mid+1,r,o<<1|1); 98 } 99 ll ans=0; 100 if(ql<=mid) ans+=query(ql,qr,l,mid,o<<1); 101 if(qr>mid) ans+=query(ql,qr,mid+1,r,o<<1|1); 102 return ans; 103 } 104 105 ll lca(int x,int y) 106 { 107 ll ans=0; 108 while(top[x]!=top[y]) 109 { 110 if(dep[top[x]]<dep[top[y]]) swap(x,y); 111 ans+=query(p[top[x]],p[x],1,n,1); 112 x=fa[top[x]]; 113 } 114 if(dep[x]>dep[y]) swap(x,y); 115 ans+=query(p[x],p[y],1,n,1); 116 return ans; 117 } 118 119 int main() 120 { 121 //freopen("in.txt","r",stdin); 122 while(~scanf("%d%d",&n,&m)) 123 { 124 for(int i=1;i<=n;i++) {G[i].clear();scanf("%d",&val[i]);} 125 for(int i=1;i<n;i++) 126 { 127 int u,v; 128 scanf("%d%d",&u,&v); 129 G[u].push_back(v); 130 G[v].push_back(u); 131 } 132 dfs(1,-1,0); 133 pos=1; 134 getpos(1,1); 135 build(1,n,1); 136 for(int i=1;i<=m;i++) 137 { 138 scanf("%d%d%d%d",&s,&e,&a,&b); 139 ans[i]=lca(s,e); 140 } 141 for(int i=1;i<=m;i++) 142 printf("%lld%c",ans[i],i==m?'\n':' '); 143 } 144 return 0; 145 }