zoukankan      html  css  js  c++  java
  • $SP3978$ $DISQUERY$ $-$ $Distance$ $Query$

    链接

    背景

    (COI) (2006)(2009.2.28)(SP) (3978)

    题意

    给定 (n) 个点构成的一棵无根树, (m) 次询问 (x,y) 两点间的最长边和最短边。

    解法

    注意到给出的是一棵无根树,不妨设根为 (1) 号节点使其成为一棵有根树。对于每次询问,实际上只需要找出 (x)(x,y) 的最近公共祖先路径上的最值以及 (y)(x,y) 的最近公共祖先路径上的最值取最值即可。这与通过求最近公共祖先来求树上路径长度的过程有异曲同工之妙。
    不妨设 (minn_{x,i}) 表示 (x) 节点向上跳 (2^i) 步后所有经过的边的最小值, (maxn_{x,i}) 表示 (x) 节点向上跳 (2^i) 步后所有经过的边的最大值,然后在 (bfs) 预处理倍增数组的同时预处理 (minn_{x,i})(maxn_{x,i}) 即可。
    每次查询 (x,y) 的最近公共祖先时,在向上跳的过程中不断更新最值即可。
    此题本质上就是在倍增法求最近公共祖先模板上套了一个取最值的运算。

    细节

    (1.) 请务必注意预处理 (minn_{x,i})(maxn_{x,i}) 的方法。以预处理 (minn_{x,i}) 为例,公式为 (minn_{x,i}=min { minn_{x,i-1},minn{f_{x,i-1},i-1} }) ,表示 (x) 节点向上跳 (2^{i-1}) 步经过所有边的最小值和 (x) 节点向上跳 (2^{i-1}) 步后的新节点 (x') 节点向上跳 (2^{i-1}) 步经过所有边的最小值取更小的值,里面的 (f_{x,i-1}) 表示的是点,而不是具体的某个数值。
    (2.) 请注意查询 (x,y) 的最近公共祖先时更新最值的顺序。先用当前的节点更新权值,再向上跳。
    (3.) 请注意查询 (x,y) 的最近公共祖先的最后一步还要从 (x,y) 两节点各跳一步,因此还要各更新一次最值。

    代码

    $View$ $Code$ ```cpp #include using namespace std; inline int read() { int ret=0,f=1; char ch=getchar(); while(ch>'9'||ch<'0') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { ret=(ret<<1)+(ret<<3)+ch-'0'; ch=getchar(); } return ret*f; } int n,m,t,x,y,w,ans_min,ans_max; int f[100005][18],d[100005],dis[100005],minn[100005][18],maxn[100005][18]; int num,head[200005]; queue q; struct edge { int ver,nxt,w; }e[200005]; inline void adde(int u,int v,int w) { e[++num].ver=v; e[num].nxt=head[u]; e[num].w=w; head[u]=num; } inline void bfs() { d[1]=1; q.push(1); while(!q.empty()) { int x=q.front(); q.pop(); for(register int i=head[x];i;i=e[i].nxt) { int y=e[i].ver; if(d[y]) continue; d[y]=d[x]+1; dis[y]=dis[x]+e[i].w; f[y][0]=x; minn[y][0]=e[i].w; maxn[y][0]=e[i].w; for(register int j=1;j<=t;j++) { f[y][j]=f[f[y][j-1]][j-1]; minn[y][j]=min(minn[y][j-1],minn[f[y][j-1]][j-1]); maxn[y][j]=max(maxn[y][j-1],maxn[f[y][j-1]][j-1]); } q.push(y); } } } inline void lca(int x,int y) { if(d[x]
  • 相关阅读:
    html优化
    HTML练习(网页计算器)
    hdu--4574 Bombs(dfs)
    Robots at Warehouse(搜索+vector的使用)
    poj 2111 Millenium Leapcow(记忆化搜索)
    Codeforces Round #408 (Div. 2) C. Bank Hacking(暴力啊!暴力)
    Gym
    Gym
    浙江省赛--D
    浙江省赛--C
  • 原文地址:https://www.cnblogs.com/Peter0701/p/11728647.html
Copyright © 2011-2022 走看看