Road
来源:互联网 发布:做结构设计的基本软件 编辑:程序博客网 时间:2024/05/22 04:43
题目
数据约定:
对于30%的数据, 1≤N,M≤100
对于60%的数据,1≤N,M≤1000
对于100%的数据,1≤N,M≤50000
题意
就是给你一颗n个点的无根树,每个点都有一个货物,都有价格。
然后给你m个询问,每个询问问你从x->y的路径中你有序的选两个货物,ai,aj
使得ai-aj最大。注意选的时候一定要有顺序。
分析
题目是关于树的,我们可以发现,从x->y的路径中一定会经过它们的最近公共祖先。
所以我们可以分类讨论,有三种情况:
1.在x->lca(x,y)中完成买和卖
2.在lca(x,y)->y中完成买和卖
3.在x->lca(x,y)中买了,在lca(x,y)->y中卖出
其中第三种情况比较简单,只需要算出两个rmq一个最大,一个最小
然后在x->lca(x,y)里面算出最小值,在lca(x,y)->y里面算出最大值即可。
但是第一第二种情况我们不能这样算的原因是我们不能保证它们的先后顺序。
难道这样就是错的,不行,我们继续思考。
能不能也用一个rmq数组去统计这一段的先卖后买的答案呢?
我们发现这样是可以的:
我们设g[i,j]表示第i个节点往上
f[i,j]表示第i个节点往上
q[i,j]表示第i个节点往上
u[i,j]表示第i个节点往上
g[i,j]=g[g[i,j-1],j-1];
f[i,j]=min(f[g[i,j-1],j-1],f[i,j-1]);
q[i,j]=max(q[g[i,j-1],j-1],q[i,j-1]);
u[i,j]=max(u[i,j-1],u[g[i,j-1],j-1],f[i,j-1]+q[g[i,j-1,j-1]);
这样我们就可以从x跳到lca(x,y),和lca(x,y)跳到y的路径中计算答案。
计算答案:
1.在x->lca(x,y)中完成买和卖:
我们不仅每次取跳上去时u的答案,还要每次记录前面的最小值,然后和后面的最大值的差作比较。
2.在lca(x,y)->y中完成买和卖:同理这里也是
3.在x->lca(x,y)中买了,在lca(x,y)->y中卖出:这里就直接取最大值最小值作差即可。
代码
#include<iostream>#include<cmath> #include<cstring>#include<algorithm>#include<cstdio>#include<cstdlib>#define maxlongint 2147483647using namespace std;const int N=50005;int nu,n,b[N*2],las[N],nex[N*2],m,x,y,val[N],g[N][20],f[N][20],q[N][20],u[N][20][2],d[N],fa[N];void insert(int x,int y){ b[++nu]=y;nex[nu]=las[x];las[x]=nu;}void dfs(int x,int y){ for(int p=las[x];p;p=nex[p]){ if (b[p]!=y) { d[b[p]]=d[x]+1; g[b[p]][0]=x; fa[b[p]]=x; f[b[p]][0]=min(val[b[p]],val[x]); q[b[p]][0]=max(val[b[p]],val[x]); u[b[p]][0][1]=max(0,val[b[p]]-val[x]); u[b[p]][0][0]=max(0,val[x]-val[b[p]]); dfs(b[p],x); } }}int lca(int x,int y){ if (d[x]<d[y]) swap(x,y); int k=trunc(log(d[x]-d[y]+1)/log(2)); while (k>=0){ if (d[g[x][k]]>d[y]) x=g[x][k]; --k; } if (d[x]!=d[y]) x=g[x][0]; k=trunc(log(d[x])/log(2)); while (k>=0){ if (g[x][k]!=g[y][k]) x=g[x][k],y=g[y][k]; k--; } if (x==y) return x;else return g[x][0];}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&val[i]); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); insert(x,y); insert(y,x); } d[1]=1; dfs(1,0); for(int j=1;j<=trunc(log(n)/log(2));j++){ x=x; for(int i=1;i<=n;i++){ g[i][j]=g[g[i][j-1]][j-1]; f[i][j]=min(f[i][j-1],f[g[i][j-1]][j-1]); q[i][j]=max(q[i][j-1],q[g[i][j-1]][j-1]); u[i][j][0]=max(u[i][j-1][0],u[g[i][j-1]][j-1][0]); u[i][j][1]=max(u[i][j-1][1],u[g[i][j-1]][j-1][1]); u[i][j][0]=max(u[i][j][0],q[g[i][j-1]][j-1]-f[i][j-1]); u[i][j][1]=max(u[i][j][1],q[i][j-1]-f[g[i][j-1]][j-1]); } } scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); int z=lca(x,y); int X=x,Y=0,An=maxlongint,bn=0,ans=0; int k=trunc(log(d[x]-d[z]+1)/log(2)); bool p=0; while (k>=0){ if (d[g[X][k]]>=d[z]) { ans=max(q[X][k]-An,ans); if (!p) {Y=k;p=1;}else bn=max(bn,q[X][k]); An=min(An,f[X][k]); ans=max(ans,u[X][k][0]);X=g[X][k]; }--k; } ans=max(ans,bn-f[x][Y]); Y=y; k=trunc(log(d[Y]-d[z]+1)/log(2)),bn=maxlongint,X=0; int Cn=0; p=0; while (k>=0){ if (d[g[Y][k]]>=d[z]) { ans=max(Cn-f[Y][k],ans); if (!p) {X=k;p=1;}else bn=min(bn,f[Y][k]); Cn=max(Cn,q[Y][k]); ans=max(ans,u[Y][k][1]);Y=g[Y][k]; }--k; } ans=max(max(ans,Cn-An),ans); if (p) ans=max(ans,q[y][X]-bn); printf("%d\n",ans); }}
- road
- Road
- Road
- Road
- Road
- road
- Road trip
- Road Layer
- Linear Road
- Forever Road
- Hard Road
- Road Construction
- My road
- Road Improvement
- My Road
- .NET2015 road
- HDU5669 Road
- Road HDU
- 微信支付基本流程
- HihoCoder 1014 : Trie树
- 深入剖析Android四大组件(九)——Activity之AppCompatActivity与toolbar的结合
- UVa 12171 Sculpture
- Hive内表与外表
- Road
- 深入理解jQuery插件开发
- android获取手机配置具体代码
- JSP连接MySQL时出现--错误:Access denied for user 'root'@'localhost' (using password: YES)'解决方案
- swift网络请求的相关方法
- git pull Checkout conflict with files:
- iOS设置view的边框、圆角、颜色
- 【DOM学习笔记-Unit03】
- 极光推送初遇