题意:给出一个图,先求出最大生成树,然后多次询问树上路径\(u→v\)的有向最大极差\(max(a_i-a_j),i>j\),其中\(i\)和\(j\)指代节点在路径中出现的顺序

极差具有单调性和可相交,因此可以用倍增来合并答案求解

维护变量

\(mx[i][j]\):\(i\)节点到\(i\)的第\(2^j\)个祖先的最大值

\(mn[i][j]\):\(i\)节点到\(i\)的第\(2^j\)个祖先的最小值

\(f[i][j]\):\(i\)节点到\(i\)的第\(2^j\)个祖先的最大极差

\(g[i][j]\):\(i\)的第\(2^j\)个祖先到\(i\)节点的最大极差

每次询问就是\(u,lca(u,v),v\)的分类讨论

答案可能是

\(u→lca(u,v)\)的最大极差

\(lca(u,v)→v\)的最大极差

\(u->lca(u,v)\)的最小值和\(lca(u,v)→v\)的最大值的差

注意查询极差时要额外维护\(u/v\)到当前节点的最大/最小值来合并单链的最优解(留意顺序的先后)

还有是先dfs还是先递推的细节问题(WA成狗)

如果问题带修改那就强上树剖吧

#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define println(a) printf("%lld\n",(ll)a)
using namespace std;
const int MAXN = 1e5+11;
typedef long long ll;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],cost[MAXN<<1],head[MAXN],tot;
int pp[MAXN];
int p[MAXN][17],dep[MAXN];
int mn[MAXN][17],mx[MAXN][17];
int f[MAXN][17],g[MAXN][17];
int a[MAXN];
bool vis[MAXN];
struct EDGE{
int from,to,cost;
EDGE(){}
EDGE(int f,int t,int c){
from=f;
to=t;
cost=c;
}
bool operator<(const EDGE &rhs)const{
return cost>rhs.cost;
}
}e[MAXN];
void init(){
memset(head,-1,sizeof head);
memset(f,0,sizeof f);
memset(g,0,sizeof g);
memset(mx,0,sizeof mx);
memset(mn,0x3f,sizeof mn);
memset(vis,0,sizeof vis);
tot=0;
}
void add(int u,int v){
to[tot]=v;
nxt[tot]=head[u];
head[u]=tot++;
}
int find(int x){return x==pp[x]?x:pp[x]=find(pp[x]);}
ll MST(int n,int m){
sort(e+1,e+1+m);
ll ans=0;
rep(i,0,n) pp[i]=i;
rep(i,1,m){
int u=e[i].from;
int v=e[i].to;
int w=e[i].cost;
int aa=find(u),bb=find(v);
if(aa==bb) continue;
pp[aa]=bb;
ans+=1ll*w;
add(u,v); add(v,u);
}
return ans;
}
void dfs(int u,int fa,int d){
dep[u]=d; vis[u]=1;
if(fa==-1) rep(j,0,16) p[u][j]=u,mn[u][j]=mx[u][j]=a[u];
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(v==fa||vis[v]) continue;
rep(j,0,16){
if(j){
p[v][j]=p[p[v][j-1]][j-1];
mx[v][j]=max(mx[v][j-1],mx[p[v][j-1]][j-1]);
mn[v][j]=min(mn[v][j-1],mn[p[v][j-1]][j-1]);
f[v][j]=max(f[v][j-1],f[p[v][j-1]][j-1]);
g[v][j]=max(g[v][j-1],g[p[v][j-1]][j-1]);
f[v][j]=max(f[v][j],mx[p[v][j-1]][j-1]-mn[v][j-1]);
g[v][j]=max(g[v][j],mx[v][j-1]-mn[p[v][j-1]][j-1]);
}else{
p[v][j]=u;
mn[v][j]=min(a[v],a[u]);
mx[v][j]=max(a[v],a[u]);
f[v][j]=a[u]-a[v];
g[v][j]=a[v]-a[u];
}
}
dfs(v,u,d+1);
}
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int d=dep[u]-dep[v];
rep(j,0,16) if(d>>j&1){
u=p[u][j];
}
if(u==v) return u;
rrep(j,16,0) if(p[u][j]!=p[v][j]){
u=p[u][j];
v=p[v][j];
}
return p[u][0];
}
int MIN(int u,int anc){
int d=dep[u]-dep[anc];
int ans=1<<30;
rep(j,0,16) if(d>>j&1){
ans=min(ans,mn[u][j]);
u=p[u][j];
}
return ans;
}
int MAX(int u,int anc){
int d=dep[u]-dep[anc];
int ans=0;
rep(j,0,16) if(d>>j&1){
ans=max(ans,mx[u][j]);
u=p[u][j];
}
return ans;
}
int LEFT(int u,int anc){
int d=dep[u]-dep[anc];
int ans=0;
int tmin=1<<29;
rep(j,0,16) if(d>>j&1){
ans=max(ans,f[u][j]);
ans=max(ans,mx[u][j]-tmin);
tmin=min(tmin,mn[u][j]);
u=p[u][j];
}
return ans;
}
int RIGHT(int u,int anc){
int d=dep[u]-dep[anc];
int ans=0,tmax=0;
rep(j,0,16) if(d>>j&1){
ans=max(ans,g[u][j]);
ans=max(ans,tmax-mn[u][j]);
tmax=max(tmax,mx[u][j]);
u=p[u][j];
}
return ans;
}
int main(){
int n;
while(~scanf("%d",&n)){
init();
rep(i,1,n) a[i]=read();
int m=read();
rep(i,1,m){
int u=read();
int v=read();
int w=read();
e[i]=EDGE(u,v,w);
}
println(MST(n,m));
rep(i,1,n) if(!vis[i]) dfs(i,-1,1);
int q=read();
while(q--){
int u=read();
int v=read();
int anc=lca(u,v);
int ans=MAX(v,anc)-MIN(u,anc);
ans=max(ans,LEFT(u,anc));
ans=max(ans,RIGHT(v,anc));
println(max(0,ans));
}
}
return 0;
}

ZOJ - 3649 树上倍增的更多相关文章

  1. Social Net ZOJ - 3649

    Social Net ZOJ - 3649 题意: 反正原题题意我是看不懂... 参考:http://www.cnblogs.com/names-yc/p/4922867.html 给出一幅图,求最大 ...

  2. LCA离线Tarjan,树上倍增入门题

    离线Tarjian,来个JVxie大佬博客最近公共祖先LCA(Tarjan算法)的思考和算法实现,还有zhouzhendong大佬的LCA算法解析-Tarjan&倍增&RMQ(其实你们 ...

  3. Codevs 2370 小机房的树 LCA 树上倍增

    题目描述 Description 小机房有棵焕狗种的树,树上有N个节点,节点标号为0到N-1,有两只虫子名叫飘狗和大吉狗,分居在两个不同的节点上.有一天,他们想爬到一个节点上去搞基,但是作为两只虫子, ...

  4. NOIP2013 货车运输 (最大生成树+树上倍增LCA)

    死磕一道题,中间发现倍增还是掌握的不熟 ,而且深刻理解:SB错误毁一生,憋了近2个小时才调对,不过还好一遍AC省了更多的事,不然我一定会疯掉的... 3287 货车运输 2013年NOIP全国联赛提高 ...

  5. HDU 4822 Tri-war(LCA树上倍增)(2013 Asia Regional Changchun)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822 Problem Description Three countries, Red, Yellow ...

  6. [NOIP2013/Codevs3287]货车运输-最小[大]生成树-树上倍增

    Problem 树上倍增 题目大意 给出一个图,给出若干个点对u,v,求u,v的一条路径,该路径上最小的边权值最大. Solution 看到这个题第一反应是图论.. 然而,任意路径最小的边权值最大,如 ...

  7. 树上倍增求LCA及例题

    先瞎扯几句 树上倍增的经典应用是求两个节点的LCA 当然它的作用不仅限于求LCA,还可以维护节点的很多信息 求LCA的方法除了倍增之外,还有树链剖分.离线tarjan ,这两种日后再讲(众人:其实是你 ...

  8. [树上倍增+二分答案][NOIP2012]运输计划

    题目背景 公元 2044 年,人类进入了宇宙纪元. 题目描述 公元 2044 年,人类进入了宇宙纪元 L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间,这 n-1n− ...

  9. 两种lca的求法:树上倍增,tarjan

    第一种:树上倍增 f[x,k]表示x的2^k辈祖先,即x向根结点走2^k步达到的结点. 初始条件:f[x][0]=fa[x] 递推式:f[x][k]=f[ f[x][k-1] ][k-1] 一次bfs ...

随机推荐

  1. code1744 方格染色

    稍微复杂一点的划分dp 设f[i][j][k]为第i行前j个k次粉刷正确的最大值 由于每行循环使用,可以去掉第一维,但每次不要忘了清零(卡了好久) f[j][k]=max{ f[u][j-1] + m ...

  2. [JAVA] 冻结Excel的第一行或第一列

    可以按照如下设置创建冻结窗口. sheet.createFreezePane( 3, 2, 3, 2 ); 前两个参数是你要用来拆分的列数和行数.后两个参数是下面窗口的可见象限,其中第三个参数是右边区 ...

  3. HUST软测1504班第4周小组作业成绩:WordCount优化

    说明 本次公布的成绩为第四周作业的结果: 第4周小组作业:WordCount优化 博客推荐:本次作业有一位同学完成有创意,推荐优秀博客.(优秀博客不会对成绩带来正面或者负面影响)PS:做任何创新的任务 ...

  4. CodeForces 427A Police Recruits (水题)

    题意:给定 n 个数,有正数和-1, -1表示罪犯,正数表示招了几个警察,一个警察只能看一个罪犯,并且要按顺序,问你有多少罪犯逃脱. 析:很简单么,从开始扫到最后,把是正数就加上,是-1判断剩余警察大 ...

  5. Python之安装第三方扩展库

    PyPI 地址:https://pypi.python.org/pypi 如果你知道你要找的库的名字,那么只需要在右上角搜索栏查找即可. 1.pip安装扩展库 (1)安装最新版本的扩展库: cmd&g ...

  6. SpringCloud 教程 | 第一篇: 服务的注册与发现Eureka(Finchley版本)

    一.spring cloud简介 鉴于<史上最简单的Spring Cloud教程>很受读者欢迎,再次我特意升级了一下版本,目前支持的版本为Spring Boot版本2.0.3.RELEAS ...

  7. linux 分区 文件系统

    操作系统通过文件系统管理文件及数据,磁盘或分区需要创建文件系统之后才能为操作系统使用,创建文件系统的过程又称之为格式化. 没有文件系统的设备称之为裸设备(raw); 常见的文件系统有fat32,NTF ...

  8. HDU 1496

    题目出处:HDU OJ 1496 http://acm.hdu.edu.cn/showproblem.php?pid=1496 为了练习Hash,特定采用了杭电自带的分类列表http://acm.hd ...

  9. tensorflow使用

    近期在工作中使用tensorflow训练神经网络模型,使用方法简要记录. 环境配置

  10. Android 打开URL中的网页和拨打电话、发送短信功能

    拨打电话需要的权限 <uses-permission android:name="android.permission.CALL_PHONE"/> 为了省事界面都写一起 ...