Yaoge’s maximum profit HDU - 5052
Yaoge’s maximum profit
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
题目链接
http://acm.hdu.edu.cn/showproblem.php?pid=5052
Problem Description
Yaoge likes to eat chicken chops late at night. Yaoge has eaten too
many chicken chops, so that Yaoge knows the pattern in the world of
chicken chops. There are N cities in the world numbered from 1 to N .
There are some roads between some cities, and there is one and only one
simple path between each pair of cities, i.e. the cities are connected
like a tree. When Yaoge moves along a path, Yaoge can choose one city to
buy ONE chicken chop and sell it in a city after the city Yaoge buy it.
So Yaoge can get profit if Yaoge sell the chicken chop with higher
price. Yaoge is famous in the world. AFTER Yaoge has completed one
travel, the price of the chicken chop in each city on that travel path
will be increased by V .
Input
The first line contains an integer T (0 < T ≤ 10), the number
of test cases you need to solve. For each test case, the first line
contains an integer N (0 < N ≤ 50000), the number of cities. For
each of the next N lines, the i-th line contains an integer Wi(0 < Wi
≤ 10000), the price of the chicken chop in city i. Each of the next N -
1 lines contains two integers X Y (1 ≤ X, Y ≤ N ), describing a road
between city X and city Y . The next line contains an integer Q(0 ≤ Q ≤
50000), the number of queries. Each of the next Q lines contains three
integer X Y V(1 ≤ X, Y ≤ N ; 0 < V ≤ 10000), meaning that Yaoge moves
along the path from city X to city Y , and the price of the chicken
chop in each city on the path will be increased by V AFTER Yaoge has
completed this travel.
Output
For each query, output the maximum profit Yaoge can get. If no positive profit can be earned, output 0 instead.
Sample Input
1
5
1
2
3
4
5
1 2
2 3
3 4
4 5
5
1 5 1
5 1 1
1 1 2
5 1 1
1 2 1
Sample Output
4
0
0
1
0
Source
题意
给你一棵树,每次询问, 从x到y的有向路径,路径上任意一点有一个商品,要求在路径上任意一点i买商品,然后在它之后的点j卖掉,求最多能赚多少钱。
然后把路径上的每个点的权值加上一个给定的值。
题解
因为路径有方向,所以肯定不是最大值减最小值那么简单,但是树链剖分肯定是少不了的,因为树剖可以把树上问题转化成区间问题。
主要是在一个区间里,线段树如何解决这个问题。
我们可以先想一想线段树主要处理什么类型的问题。
线段树是先将区间分成两半,然后依次处理两边,再整合到一起,顺着这个思路想。
我们假设左右区间已经得到了答案,那么我们整个区间的答案就有三种可能:
1.左区间的答案
2.右区间的答案
3.右边的最大值-左边的最大值
所以我们只需要记录区间最大值、最小值和答案即可,如果有lazy标记,就像平常一样处理就行。
还有一点需要注意就是x-->y那么x-->lca(x,y)区间是倒过来的,我们需要存赚的最小值,然后取相反数。
细节还是有点小麻烦,最好对树链剖分打的比较熟,并有一定的理解,再来切这道题。
代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define N 200050 5 const int INF=1e9; 6 struct Tree{int l,r,j,mi,mx,qmi,qmx;}tr[N<<2]; 7 struct Query{int mi,mx,qmi,qmx;}; 8 struct Edge{int from,to,s;}edges[N<<1]; 9 int n,m,w[N]; 10 int tot,last[N]; 11 int cnt,fa[N],dp[N],size[N],son[N],rk[N],kth[N],top[N]; 12 template<typename T>void read(T&x) 13 { 14 ll k=0; char c=getchar(); 15 x=0; 16 while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar(); 17 if (c==EOF)exit(0); 18 while(isdigit(c))x=x*10+c-'0',c=getchar(); 19 x=k?-x:x; 20 } 21 void read_char(char &c) 22 {while(!isalpha(c=getchar())&&c!=EOF);} 23 void AddEdge(int x,int y) 24 { 25 edges[++tot]=Edge{x,y,last[x]}; 26 last[x]=tot; 27 } 28 template<typename T>void he(T &c,T a,T b) 29 { 30 c.mx=max(a.mx,b.mx); 31 c.mi=min(a.mi,b.mi); 32 c.qmi=min(a.qmi,b.qmi); 33 c.qmx=max(a.qmx,b.qmx); 34 c.qmi=min(c.qmi,b.mi-a.mx); 35 c.qmx=max(c.qmx,b.mx-a.mi); 36 } 37 void push_up(int x) 38 { 39 Tree &a=tr[x<<1],&b=tr[x<<1|1]; 40 int len=tr[x].r-tr[x].l+1; 41 if (len>1) he(tr[x],a,b); 42 else tr[x].mx=tr[x].mi=0; 43 tr[x].mx+=tr[x].j; 44 tr[x].mi+=tr[x].j; 45 } 46 void push_down(int x) 47 { 48 Tree &a=tr[x<<1],&b=tr[x<<1|1]; 49 a.j+=tr[x].j; 50 b.j+=tr[x].j; 51 push_up(x<<1); 52 push_up(x<<1|1); 53 tr[x].j=0; 54 } 55 void bt(int x,int l,int r) 56 { 57 tr[x].l=l; tr[x].r=r; tr[x].j=0; 58 if (l==r) 59 { 60 tr[x].qmi=tr[x].qmx=0; 61 tr[x].j=w[kth[l]]; 62 push_up(x); 63 return; 64 } 65 int mid=(l+r)>>1; 66 bt(x<<1,l,mid); 67 bt(x<<1|1,mid+1,r); 68 push_up(x); 69 } 70 void update(int x,int l,int r,int tt) 71 { 72 if (l<=tr[x].l&&tr[x].r<=r) 73 { 74 tr[x].j+=tt; 75 push_up(x); 76 return; 77 } 78 int mid=(tr[x].l+tr[x].r)>>1; 79 push_down(x); 80 if(l<=mid)update(x<<1,l,r,tt); 81 if(mid<r)update(x<<1|1,l,r,tt); 82 push_up(x); 83 } 84 Query query(int x,int l,int r) 85 { 86 if (l<=tr[x].l&&tr[x].r<=r) 87 return Query{tr[x].mi,tr[x].mx,tr[x].qmi,tr[x].qmx}; 88 int mid=(tr[x].l+tr[x].r)>>1; 89 Query tp1=Query{INF,-INF,0,0},tp2=Query{INF,-INF,0,0},tp; 90 push_down(x); 91 if (l<=mid)tp1=query(x<<1,l,r); 92 if (mid<r)tp2=query(x<<1|1,l,r); 93 push_up(x); 94 he(tp,tp1,tp2); 95 return tp; 96 } 97 void dfs1(int x,int pre) 98 { 99 fa[x]=pre; 100 dp[x]=dp[pre]+1; 101 size[x]=1; 102 son[x]=0; 103 for(int i=last[x];i;i=edges[i].s) 104 { 105 Edge &e=edges[i]; 106 if (e.to==pre)continue; 107 dfs1(e.to,x); 108 size[x]+=size[e.to]; 109 if (size[e.to]>size[son[x]])son[x]=e.to; 110 } 111 } 112 void dfs2(int x,int y) 113 { 114 rk[x]=++cnt; 115 kth[cnt]=x; 116 top[x]=y; 117 if (son[x]==0)return; 118 dfs2(son[x],y); 119 for(int i=last[x];i;i=edges[i].s) 120 { 121 Edge &e=edges[i]; 122 if (e.to==son[x]||e.to==fa[x])continue; 123 dfs2(e.to,e.to); 124 } 125 } 126 int get_max(int x,int y) 127 { 128 int fx=top[x],fy=top[y],ans=0; 129 Query tpx={INF,-INF,0,0},tpy={INF,-INF,0,0},tp; 130 while(fx!=fy) 131 { 132 if (dp[fx]>dp[fy]) 133 { 134 tp=query(1,rk[fx],rk[x]); 135 he(tpx,tp,tpx); 136 x=fa[fx]; fx=top[x]; 137 } 138 else 139 { 140 tp=query(1,rk[fy],rk[y]); 141 he(tpy,tp,tpy); 142 y=fa[fy]; fy=top[y]; 143 } 144 } 145 if (dp[x]>dp[y]) 146 tp=query(1,rk[y],rk[x]),he(tpx,tp,tpx); 147 else 148 tp=query(1,rk[x],rk[y]),he(tpy,tp,tpy); 149 ans=max(-tpx.qmi,tpy.qmx); 150 ans=max(ans,tpy.mx-tpx.mi); 151 return ans; 152 } 153 void change(int x,int y,int tt) 154 { 155 int fx=top[x],fy=top[y]; 156 while(fx!=fy) 157 { 158 if (dp[fx]<dp[fy])swap(x,y),swap(fx,fy); 159 update(1,rk[fx],rk[x],tt); 160 x=fa[fx]; fx=top[x]; 161 } 162 if (dp[x]<dp[y])swap(x,y),swap(fx,fy); 163 update(1,rk[y],rk[x],tt); 164 } 165 void work() 166 { 167 read(n); 168 for(int i=1;i<=n;i++)read(w[i]); 169 for(int i=1;i<=n-1;i++) 170 { 171 int x,y; 172 read(x); read(y); 173 AddEdge(x,y); 174 AddEdge(y,x); 175 } 176 dfs1(1,0); 177 dfs2(1,1); 178 bt(1,1,n); 179 read(m); 180 for(int i=1;i<=m;i++) 181 { 182 int x,y,tt; 183 read(x); read(y); read(tt); 184 printf("%d\n",get_max(x,y)); 185 change(x,y,tt); 186 } 187 } 188 void clear() 189 { 190 cnt=0; tot=0; 191 memset(last,0,sizeof(last)); 192 } 193 int main() 194 { 195 #ifndef ONLINE_JUDGE 196 freopen("aa.in","r",stdin); 197 #endif 198 int q; 199 read(q); 200 while(q--) 201 { 202 clear(); 203 work(); 204 } 205 }