HDU 6162 Ch's gift(树链剖分+线段树)

 

题意:

已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点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 }

 

posted @ 2017-08-30 09:16  Kayden_Cheung  阅读(219)  评论(0编辑  收藏  举报
//目录