题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162
题意:给出一棵树的链接方法,每个点都有一个数字,询问U-》V节点经过所有路径中l < = x < = r的数字和
解法:主席树维护区间和,树剖查询,复杂度nloglog。
代码:
#include <bits/stdc++.h> using namespace std; const int maxn = 1e5+5; const int maxm = 40*maxn; typedef long long LL; int T[maxn]; int lson[maxm],rson[maxm]; LL sum[maxm]; int clk,M; int newnode(){ clk++; lson[clk]=rson[clk]=sum[clk]=0; return clk; } void update(int &now, int pre, int L, int R, int pos, int val) { now = newnode(); lson[now] = lson[pre]; rson[now] = rson[pre]; sum[now] = sum[pre] + val; if(L!=R){ int mid=(L+R)>>1; if(pos<=mid) update(lson[now],lson[pre],L,mid,pos,val); else update(rson[now],rson[pre],mid+1,R,pos,val); } } LL query(int rt, int L, int R, int l, int r){ if(l<=L&&R<=r){ return sum[rt]; } else{ int mid = (L+R)>>1; LL ret = 0; if(l <= mid) ret += query(lson[rt], L, mid, l, r); if(mid < r) ret += query(rson[rt], mid+1, R, l, r); return ret; } } struct edge{ int to,next; }E[maxn*2]; int head[maxn],edgecnt,tim; int siz[maxn],top[maxn],son[maxn],dep[maxn]; int fa[maxn],tid[maxn],Rank[maxn],val[maxn]; void init(){ edgecnt=tim=0; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); clk=M=0; lson[clk]=rson[clk]=sum[clk]=0; } void add(int u, int v){ E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++; } void dfs1(int u, int pre, int d){ dep[u]=d; fa[u]=pre; siz[u]=1; for(int i=head[u];~i;i=E[i].next){ int v=E[i].to; if(v!=pre){ dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } } void dfs2(int u, int tp){ top[u]=tp; tid[u]=++tim; Rank[tid[u]]=u; if(son[u]==-1) return; dfs2(son[u],tp); for(int i=head[u];~i;i=E[i].next){ int v=E[i].to; if(v!=son[u]&&v!=fa[u]){ dfs2(v,v); } } } int LCA(int u, int v) { int ret; while(true) { if(top[u] == top[v]) { ret = dep[u] < dep[v] ? u : v; break; } else if(dep[top[u]] > dep[top[v]]) u = fa[top[u]]; else v = fa[top[v]]; } return ret; } int t[maxn]; LL query(int u, int v, int a, int b) { a = lower_bound(t + 1, t + 1 + M, a) - t - 1; b = upper_bound(t + 1, t + 1 + M, b) - t - 1; if(b == 0) return 0; LL ret = 0; while(top[u] != top[v]) { if(dep[top[u]] < dep[top[v]]) swap(u, v); ret += query(T[tid[u]], 1, M, 1, b); ret -= query(T[tid[top[u]] - 1], 1, M, 1, b); if(a) { ret -= query(T[tid[u]], 1, M, 1, a); ret += query(T[tid[top[u]] - 1], 1, M, 1, a); } u = fa[top[u]]; } if(dep[u] < dep[v]) swap(u, v); ret += query(T[tid[u]], 1, M, 1, b); ret -= query(T[tid[v] - 1], 1, M, 1, b); if(a) { ret -= query(T[tid[u]], 1, M, 1, a); ret += query(T[tid[v] - 1], 1, M, 1, a); } return ret; } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { init(); for(int i=1; i<=n; i++){ scanf("%d", &val[i]); t[i]=val[i]; } for(int i=1; i<n; i++){ int u,v; scanf("%d %d", &u,&v); add(u, v); add(v, u); } dfs1(1,0,0); dfs2(1,1); sort(t+1,t+n+1); M = unique(t+1, t+n+1)-t-1; for(int i=1; i<=n; i++) val[i] = lower_bound(t+1, t+1+M, val[i])-t; for(int i=1; i<=n; i++){ T[i] = T[i-1]; update(T[i],T[i],1,M,val[Rank[i]],t[val[Rank[i]]]); } for(int i=1; i<=m; i++){ int u,v,x,y; scanf("%d %d %d %d", &u,&v,&x,&y); LL ret = query(u,v,x,y); printf("%lld", ret); if(i == m){ printf(" "); } else{ printf(" "); } } } return 0; }