BZOJ4539: [Hnoi2016]树 (倍增)_bzoj 4539_DZYO的博客-程序员宝宝

技术标签: 倍增  

传送门

题解:

一开始看错题了以为可以拷贝新加的点的,仔细一看是一道倍增裸题。
首先建一颗虚树,只存拷贝的根节点。
注意到询问两点最后肯定是到某个虚树的节点内部求 lca l c a 。那么直接在虚树上倍增到同一个节点再在原树上倍增到 lca l c a 即可。 时间复杂度 O(nlogn) O ( n log ⁡ n )
注意还要求的是一个子树中第 k k 大的节点是哪一个,这个直接用 d f s 转为区间第 k k <script type="math/tex" id="MathJax-Element-108">k</script>大就行了。

#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
inline LL rd() {
    char ch=getchar(); LL i=0,f=1;
    while(!isdigit(ch)) {
   if(ch=='-')f=-1; ch=getchar();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
    return i*f;
}
inline void W(LL x) {
    static int buf[50];
    if(!x) {
   putchar('0'); return;}
    if(x<0) {
   putchar('-');x=-x;}
    while(x) {buf[++buf[0]]=x%10; x/=10;}
    while(buf[0]) {
   putchar(buf[buf[0]--]+'0');}
}
const int N=1e5+50;
int n,m,q;
int rt[N],lc[N*30],rc[N*30],sze[N*30],tot;
int dfn[N],last[N],dep[N],fa[N][20],ind;
vector <int> edge[N];
LL totid,cnt,vdis[N],vdep[N],vfa[N][20],vrt[N],vbg[N],vofa[N],bg[N],rt2[N],rt3[N];
set < pair<LL,int> > S;
inline int copy(int x) {++tot; lc[tot]=lc[x]; rc[tot]=rc[x]; sze[tot]=sze[x]; return tot;}
inline void inc(int x,int &y,int l,int r,int p) {
    y=copy(x); ++sze[y]; if(l==r) return;
    int mid=(l+r)>>1;
    (p<=mid)?inc(lc[x],lc[y],l,mid,p):inc(rc[x],rc[y],mid+1,r,p);
}
inline void dfs(int x,int f) {
    dfn[x]=++ind; dep[x]=dep[f]+1; fa[x][0]=f;
    inc(rt[ind-1],rt[ind],1,n,x);
    for(int i=1;i<=18;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int e=edge[x].size()-1;e>=0;e--) {
        int v=edge[x][e]; if(v==f) continue;
        dfs(v,x);
    }
    last[x]=ind;
}
const int INF=0x3f3f3f3f;
inline int getid(LL to) {
   return (--S.upper_bound(make_pair(to,INF)))->second;}
inline int getlca(int x,int y) {
    if(dep[x]<dep[y]) swap(x,y);
    int d=dep[x]-dep[y];
    for(int i=0;i<=18;i++) if(d&(1<<i)) x=fa[x][i];
    if(x==y) return x;
    for(int i=18;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
inline int calc_dis(int x,int y) {
   return dep[x]+dep[y]-2*dep[getlca(x,y)];}
inline int kth(int x,int y,int l,int r,int k) {
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(sze[lc[y]]-sze[lc[x]]>=k) return kth(lc[x],lc[y],l,mid,k);
    else return kth(rc[x],rc[y],mid+1,r,k-sze[lc[y]]+sze[lc[x]]);
}
inline int rk(int x,int y,int l,int r,int v) {
    if(l==r) return sze[y]-sze[x];
    int mid=(l+r)>>1;
    if(v<=mid) return rk(lc[x],lc[y],l,mid,v);
    else return sze[lc[y]]-sze[lc[x]]+rk(rc[x],rc[y],mid+1,r,v);
}
inline int kth(int x,int k) {
   return kth(rt[dfn[x]-1],rt[last[x]],1,n,k);}
inline int rk(int x,int k) {
   return rk(rt[dfn[x]-1],rt[last[x]],1,n,k);}
int main() {
    n=rd(), m=rd(), q=rd();
    for(int i=1;i<n;i++) {
        int x=rd(), y=rd();
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    dfs(1,0);
    totid=n;  rt3[1]=1; 
    S.insert(make_pair(1,cnt=1)); 
    for(int i=1;i<=m;i++) {
        int x=rd(); LL to=rd();
        S.insert(make_pair(totid+1,++cnt));
        bg[cnt]=totid+1;
        totid+=last[x]-dfn[x]+1;
        LL r=getid(to);
        vfa[cnt][0]=r; vofa[cnt]=to; 
        vdep[cnt]=vdep[r]+1;
        rt2[cnt]=x; rt3[cnt]=rk(x,x)+bg[cnt]-1;
        vdis[cnt]=vdis[r]+(to>n?calc_dis(kth(rt2[r],to-bg[r]+1),rt2[r]):dep[to]-1)+1;
        for(int i=1;i<=18;i++) vfa[cnt][i]=vfa[vfa[cnt][i-1]][i-1];
    }
    for(int i=1;i<=q;i++) {
        LL x=rd(), y=rd(), ans=0;
        int idx=getid(x), idy=getid(y);
        if(vdep[idx]<vdep[idy]) swap(idx,idy), swap(x,y);
        if(vdep[idx]!=vdep[idy]) {
            if(x!=rt3[idx]) {
                ans+=calc_dis(rt2[idx],kth(rt2[idx],x-bg[idx]+1));
                x=rt3[idx];
            }
            int d=vdep[idx]-vdep[idy]-1;
            for(int i=0;i<=18;i++) {
                if(!(d&(1<<i))) continue;
                ans+=vdis[idx]-vdis[vfa[idx][i]];
                idx=vfa[idx][i]; x=rt3[idx];
            }
            ++ans; x=vofa[idx]; idx=vfa[idx][0];
        }
        if(idx!=idy) {
            if(x!=rt3[idx]) {
                ans+=calc_dis(rt2[idx],kth(rt2[idx],x-bg[idx]+1));
                x=rt3[idx];
            }
            if(y!=rt3[idy]) {
                ans+=calc_dis(rt2[idy],kth(rt2[idy],y-bg[idy]+1));
                y=rt3[idy];
            }
            for(int i=18;i>=0;i--) if(vfa[idx][i]!=vfa[idy][i]) {
                ans+=vdis[idx]-vdis[vfa[idx][i]]+vdis[idy]-vdis[vfa[idy][i]];
                idx=vfa[idx][i], idy=vfa[idy][i], x=rt3[idx], y=rt3[idy];
            }
            ans+=2; x=vofa[idx], y=vofa[idy]; idx=vfa[idx][0], idy=vfa[idy][0];
        }
        if(x>n) ans+=calc_dis(kth(rt2[idx],x-bg[idx]+1),kth(rt2[idy],y-bg[idy]+1));
        else ans+=calc_dis(x,y);
        W(ans); putchar('\n');
    }
}
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_35649707/article/details/79404822

智能推荐

「小程序」开发 指南(里面是小程序开发的各种论坛和文档)_小程序开发者论坛_风铃的翼的博客-程序员宝宝

之前研究小程序,看到了一篇小程序的开发帖子,在这分享给大家。什么是微信小程序?微信之父张小龙是这样描述小程序的: 小程序是一个不需要下载安装就可使用的应用,它实现了应用触手可及的梦想,用户扫一扫或者搜一下即可打开应用。也体现了用完即走的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用,但又无需安装卸载。简单来说,小程序不用安装就能使用;它的体积也非常小,每

JavaSE——Java8之函数式接口、函数式编程、Lambda表达式_ZHBlog_的博客-程序员宝宝

一、函数式接口1、概念  函数式接口的几点特征:   函数式接口只有一个抽象方法;   default方法某默认实现,不属于抽象方法;   接口重写了Object的公共方法也不算入内。  函数式接口的应用场景:函数式编程,而在Java中的函数式编程就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中只有一个抽象方法,Lambda表达式才能顺利的进行...

Java随笔-char存储_阿pin的博客-程序员宝宝

charJava基本数据类型之一,使用’ ’ 括起来,用于表示单个字符。Java中char是两个字节,但是UTF-8一般是1-3个字节,char该如何存储??

android.view.SurfaceHolder$BadSurfaceTypeException: Surface type is SURFACE__一叶飘舟的博客-程序员宝宝

原来,当SurfaceHolder对象的类型设置为SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS时就只能拍照不能绘制了,这就是为什么第二种思路程序会直接挂掉的原因。为了能够预览视频的同时绘制矩形框等信息,需要用两个同样大小的SurfaceView放在一个FrameLayout里,顶层的SurfaceView设成setZOrderOnTop(true);   setF

Python网络爬虫学习实战:爬虫快速入门_爬虫教程_千锋python和唐唐的博客-程序员宝宝

很多同学私信问爬虫的相关教程,想了想,还是专门跟大家出些Python爬虫学习相关的教程,从零开始阐述如何编写Python网络爬虫,以及网络爬虫中容易遇到的问题,比如具有反爬加密的网站,还有爬虫拿不到数据,以及登录验证等问题,会伴随大量网站的爬虫实战来进行。我们编写网络爬虫最主要的目的是爬取想要的数据还有通过爬虫去自动完成我们想在网站中做的一些事情。这里我会从基础开始讲解如何通过网络爬虫去完成你...

DSP 连不上 JTAG, 'SC_ERR_PATH_BROKEN', 关注EMU1 EMU0_不纯洁的锌的博客-程序员宝宝

早先设计28335的板子,有EMU0 EMU1两线和DSP上两个引脚对应。这次做28069的原理图时,看到没有这两个对应引脚,网上查了一下EMU0 EMU1似乎也没什么用途,于是就把2条线省去。板子焊出来后,发现JTAG连不上芯片。报错如下:/*********************************************************************分割线

随便推点

运行.bat文件乱码?Win11系统bat输出中文乱码的解决方法_bat执行乱码_小白一键重装系统的博客-程序员宝宝

​近期有部分Win11用户在果bat批处理文件中输入中文,导致出现运行.bat文件乱码的情况,对于这种情况我们应该如何解决呢?如果你也有同样的困扰,不妨来看看下面这篇小编带来的详细的解决教程吧,希望对你有所帮助哦。如何重装系统  1、运行bat批处理文件的时候,只要输出中文,就会出现乱码;  2、选中出现问题的bat批处理文件,点击右键,在打开的菜单项中,选择【显示更多选项 - 编辑】;  3、以记事本文件的方式打开bat批处理文件后,点击左上角的【文件】,在打开的下拉项中,选择【另存为】;  4、另存为窗

GB28181 PS流解析_gb c++ ps流解析类_Geek.Fan的博客-程序员宝宝

我们在一般在gb28181发送码流选择PS流,PS流再封装H264的数据。那么如何封装PS流,PS流如何封装H264呢?本文详细描述如何通过PS流解析H264码流。先研究下PSM(节目流映射),PSM头定义如下:这里找了一个标准的PS流里面的PSM数据进行研究分析:packet_start_code_prefix—24bit :00 00 01。map_stream_id-8bit:BC。program_stream_map_length-16bit:0...

目录树(一)_结构目录树_snpmyn的博客-程序员宝宝

TreeView准备Nodepackage function.tree;import com.fr.android.platform.data.bean.IFEntryNode;import java.util.ArrayList;import java.util.List;/** * @decs: Node * @date: 2018/9/7 11:20 * @v...

模型选择准则之AIC和BIC_wjz2998980038的博客-程序员宝宝

转自:HTTP://blog.csdn.net/jteng/article/details/40823675此处模型选择我们只考虑模型参数数量,不涉及模型结构的选择。很多参数估计问题均采用似然函数作为目标函数,当训练数据足够多时,可以不断提高模型精度,但是以提高模型复杂度为代价的,同时带来一个机器学习中非常普遍的问题 - 过拟合。所以,模型选择问题在模型复杂度与模型对数据集描述能力(即似然...

推荐文章

热门文章

相关标签