第九場 hdu 6162 Ch’s gift(樹鏈剖分+線段樹)

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 }
相關文章
相關標籤/搜索