code vs 3305 水果姐逛水果街Ⅱ
题目描述 Description
水果姐第二天心情也很不错,又来逛水果街。
突然,cgh又出现了。cgh施展了魔法,水果街变成了树结构(店与店之间只有一条唯一的路径)。
同样还是n家水果店,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样。
cgh给出m个问题,每个问题要求水果姐从第x家店出发到第y家店,途中只能选一家店买一个水果,然后选一家店(可以是同一家店,但不能往回走)卖出去。求最多可以赚多少钱。
水果姐向学过oi的你求助。
输入描述 Input Description
第一行n,表示有n家店
下来n个正整数,表示每家店一个苹果的价格。
下来n-1行,每行两个整数x,y,表示第x家店和第y家店有一条边。
下来一个整数m,表示下来有m个询问。
下来有m行,每行两个整数x和y,表示从第x家店出发到第y家店。
输出描述 Output Description
有m行。
每行对应一个询问,一个整数,表示面对cgh的每次询问,水果姐最多可以赚到多少钱。
样例输入 Sample Input
10
16 5 1 15 15 1 8 9 9 15
1 2
1 3
2 4
2 5
2 6
6 7
4 8
1 9
1 10
6
9 1
5 1
1 7
3 3
1 1
3 6
样例输出 Sample Output
7
11
7
0
0
15
数据范围及提示 Data Size & Hint
0<=苹果的价格<=10^8
0<n<=200000
0<m<=10000
思路:lca维护区间差值。
#include<cstdio> #include<iostream> #include<vector> #include<cstring> using namespace std; const int N=200001,pow=20,maxx=999999; vector<int> g[N]; int d[N],f[N][pow],maxv[N][pow]={0},minv[N][pow],diff[N][pow]={0},dife[N][pow]={0},q[N]; // diff:顺区间最大差 // dife:逆区间最大差 void dfs(int x,int fa) { int i,t; maxv[x][0]=max(q[x],q[fa]); minv[x][0]=min(q[x],q[fa]); diff[x][0]=q[x]-q[fa]; dife[x][0]=q[fa]-q[x]; d[x]=d[fa]+1; f[x][0]=fa; for(i=1;i<pow;i++) { f[x][i]=f[f[x][i-1]][i-1]; maxv[x][i]=max(maxv[x][i-1],maxv[f[x][i-1]][i-1]); minv[x][i]=min(minv[x][i-1],minv[f[x][i-1]][i-1]); diff[x][i]=max(maxv[x][i-1]-minv[f[x][i-1]][i-1],max(diff[x][i-1],diff[f[x][i-1]][i-1])); dife[x][i]=max(maxv[f[x][i-1]][i-1]-minv[x][i-1],max(dife[x][i-1],dife[f[x][i-1]][i-1])); } for(i=0;i<g[x].size();i++) if(g[x][i]!=fa) dfs(g[x][i],x); } int lca(int a,int b) { int i,t,total=0,flag=0,maxn=0,minn=maxx; if(d[a]>d[b]){ flag=1; a^=b,b^=a,a^=b; } if(d[a]<d[b]){ t=d[b]-d[a]; for(i=0;i<pow;i++) if(t&(1<<i)){ if(!flag){ total=max(total,maxn-minv[b][i]); maxn=max(maxn,maxv[b][i]); total=max(total,diff[b][i]); } else{ total=max(total,maxv[b][i]-minn); minn=min(minn,minv[b][i]); total=max(total,dife[b][i]); } b=f[b][i]; } if(!flag) minn=q[a]; else maxn=q[a]; } else{ if(!flag) minn=q[a],maxn=q[b]; else maxn=q[a],minn=q[b]; } if(a!=b){ for(i=pow-1;i>=0;i--) if(f[a][i]!=f[b][i]){ if(!flag){ total=max(total,maxv[a][i]-minn); total=max(total,maxn-minv[b][i]); total=max(total,dife[a][i]); total=max(total,diff[b][i]); maxn=max(maxn,maxv[b][i]); minn=min(minn,minv[a][i]); } else{ total=max(total,maxv[b][i]-minn); total=max(total,maxn-minv[a][i]); total=max(total,diff[a][i]); total=max(total,dife[b][i]); maxn=max(maxn,maxv[a][i]); minn=min(minn,minv[b][i]); } a=f[a][i],b=f[b][i]; } total=max(total,maxn-minn); if(!flag){ total=max(total,maxn-q[f[a][0]]); total=max(total,q[f[b][0]]-minn); } else{ total=max(total,maxn-q[f[b][0]]); total=max(total,q[f[a][0]]-minn); } } return total; } int main(){ memset(minv,27,sizeof(minv)); int n,m,i,j,x,y; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d",&q[i]); for(i=1;i<n;i++){ scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); } for(i=0;i<g[1].size();i++) dfs(g[1][i],1); scanf("%d",&m); for(i=1;i<=m;i++){ scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } return 0; }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。