hdu6162 Ch’s gift[树链剖分]

Problem Description

Mr. Cui is working off-campus and he misses his girl friend very much. After a whole night tossing and turning, he decides to get to his girl friend’s city and of course, with well-chosen gifts. He knows neither too low the price could a gift be since his girl friend won’t like it, nor too high of it since he might consider not worth to do. So he will only buy gifts whose price is between $[a,b]$.
There are n cities in the country and $(n-1)$ $b_i$-directional roads. Each city can be reached from any other city. In the ith city, there is a specialty of price ci Cui could buy as a gift. Cui buy at most 1 gift in a city. Cui starts his trip from city s and his girl friend is in city t. As mentioned above, Cui is so hurry that he will choose the quickest way to his girl friend(in other words, he won’t pass a city twice) and of course, buy as many as gifts as possible. Now he wants to know, how much money does he need to prepare for all the gifts?

Input

There are multiple cases.
For each case:
The first line contains tow integers n,m( $1≤n,m≤10^5$ ), representing the number of cities and the number of situations.
The second line contains n integers $C_1$,$C_2$,…,$C_n$( $1≤C_i≤10^9$), indicating the price of city i’s specialty.
Then n-1 lines follows. Each line has two integers $x$,$y$($1≤x,y≤n$), meaning there is road between city $x$ and city $y$.
Next m line follows. In each line there are four integers $s,t,a,b$($1≤s,t≤n$;$1≤a≤b≤10^9$), which indicates start city, end city, lower bound of the price, upper bound of the price, respectively, as the exact meaning mentioned in the description above

Output

Output m space-separated integers in one line, and the ith number should be the answer to the ith situation.

Sample Input

1
2
3
4
5
6
7
8
9
5 3
1 2 1 3 2
1 2
2 4
3 1
2 5
4 5 1 3
1 1 1 1
3 5 2 3

Sample Output

1
7 1 4

题目大意

给一棵树,每次问某两点之间的最短路径上,能够满足价格在 $[a,b]$ 这个范围内的价值之和是多少。

题解

求 $[a,b]$ 这个范围内的价值和相当于求 $[0,b]$ 的价值和减去 $[0,a-1]$的价值和
然后所有的修改离线掉,按从小到大的顺序加进去了,然后求解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
inline int qmax(int &x,int y) {if (x<y) x=y;}
inline int qmin(int &x,int y) {if (x>y) x=y;}
inline int read()
{
char s;int k=0,base=1;
while((s=getchar())!='-'&&s!=EOF&&!(s>='0'&&s<='9'));
if(s==EOF)exit(0);if(s=='-')base=-1,s=getchar();
while(s>='0'&&s<='9') {k=k*10+(s^'0');s=getchar();}return k*base;
}
void write(int x)
{
if(x<0){putchar('-');write(-x);}
else{if(x/10)write(x/10);putchar(x%10+'0');}
}
int n,m,LL,RR;
const int maxn=1e5+1000;
struct node {int d,p;} a[maxn];
struct node1 {int x,y;long long ans[2];} q[maxn];
struct node2 {int x,y,z;} G[maxn*2];

bool cmp(node aa,node bb) {return aa.d==bb.d?aa.p<bb.p:aa.d<bb.d;}
bool cmp1(node2 aa,node2 bb) {return aa.z<bb.z;}

int to[maxn<<1],ne[maxn<<1],po[maxn],id1,XX,YY;
inline void add(int x,int y) {to[++id1]=y;ne[id1]=po[x];po[x]=id1;}
int fa[maxn],sz[maxn],son[maxn],deep[maxn];
void dfs1(int x)
{
sz[x]=1;son[x]=0;deep[x]=deep[fa[x]]+1;
for (int i=po[x];i;i=ne[i])
if (to[i]!=fa[x])
{
fa[to[i]]=x;
dfs1(to[i]);sz[x]+=sz[to[i]];
if (sz[to[i]]>sz[son[x]]) son[x]=to[i];
}
}

int id[maxn],dfs_time,top[maxn],Map[maxn];
void dfs(int x,int last)
{
id[x]=++dfs_time;Map[dfs_time]=x;
top[x]=last;
if (son[x]==0) return;
dfs(son[x],last);
for (int i=po[x];i;i=ne[i]) if (son[x]!=to[i]&&fa[x]!=to[i]) dfs(to[i],to[i]);
}

long long t[maxn<<2];
void bt(int x,int y,int d)
{
t[d]=0;if (x==y) return;
int mid=(x+y)>>1;
bt(x,mid,d<<1);bt(mid+1,y,d<<1|1);
}
void xg(int x,int d,int l,int r,int z)
{
if (l==x&&x==r) {t[d]+=(long long)z;return;}
int mid=(l+r)>>1;
if (x<=mid) xg(x,d<<1,l,mid,z); else xg(x,d<<1|1,mid+1,r,z);
t[d]=t[d<<1]+t[d<<1|1];
}
long long qh(int x,int y,int d,int l,int r)
{
if (x<=l&&r<=y) return t[d];
int mid=(l+r)>>1;
if (y<=mid) return qh(x,y,d<<1,l,mid); else
if (x>mid) return qh(x,y,d<<1|1,mid+1,r); else
return qh(x,mid,d<<1,l,mid)+qh(mid+1,y,d<<1|1,mid+1,r);
}
long long qsum(int x,int y)
{
int tx=top[x],ty=top[y];
long long ss=0;
while (tx!=ty)
{
if (deep[tx]<deep[ty]) swap(tx,ty),swap(x,y);
ss+=qh(id[tx],id[x],1,1,n);
x=fa[tx];tx=top[x];
}
if (id[y]<id[x]) swap(x,y);
ss+=qh(id[x],id[y],1,1,n);
return ss;
}
int main()
{
while (scanf("%d",&n)!=EOF)
{
m=read();dfs_time=0; memset(po,0,sizeof(po)); id1=0;deep[1]=1;
memset(fa,0,sizeof(fa));memset(Map,0,sizeof(Map));
for (int i=1;i<=n;i++) a[i].d=read(),a[i].p=i; sort(a+1,a+n+1,cmp);//修改
for (int i=1;i<n;i++) XX=read(),YY=read(),add(XX,YY),add(YY,XX);
dfs1(1);dfs(1,1);bt(1,n,1);
for (int i=1;i<=m;i++)
{
q[i].x=read(),q[i].y=read(),LL=read(),RR=read();
G[i*2-1].x=i;G[i*2-1].y=0;G[i*2-1].z=LL-1;
G[i*2].x=i; G[i*2].y=1; G[i*2].z=RR;//离散掉询问
}
int xxx=m*2;
sort(G+1,G+xxx+1,cmp1);
int i=0,j=1;
while (i<n)
{
i++;int xx=a[i].d;
while (j<=2*m&&G[j].z<xx)
{
q[G[j].x].ans[G[j].y]=qsum(q[G[j].x].x,q[G[j].x].y);
j++;
}//查询
xg(id[a[i].p],1,1,n,xx);
while (a[i+1].d==xx&&i<n) {i++;xg(id[a[i].p],1,1,n,xx);}//修改
}
while (j<=2*m)
{
q[G[j].x].ans[G[j].y]=qsum(q[G[j].x].x,q[G[j].x].y);
j++;//最后的没有查询
}
for (int i=1;i<=m;i++)
{
printf("%lld",q[i].ans[1]-q[i].ans[0]);
if (i!=m) putchar(' ');
}
printf("\n");
}
return 0;
}