欢迎来到蒟蒻mqd的博客

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 }
View Code

 

 

 
 
posted @ 2019-04-27 22:15  mmqqdd  阅读(278)  评论(0编辑  收藏  举报