题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4539

明明就是把每次复制的一个子树当作一个点,这样能连出一个树的结构,自己竟然都没想到。思维有待加强。

找编号为 k 的点,可以通过给 dfs 序建立对于编号的主席树。可以做一个 s[ i ] 表示第 i 步操作之后一共有多少个点,二分得知编号第 k 大的点在哪一步操作建出的大点里,然后用主席树查一下具体是哪个小点即可。每个大点记录一下自己的根,还有连向父亲中的哪个小点。

处理出每个小点在原树种的倍增数组和每个大点在新树中的倍增数组,就能查距离了。每个询问用刚才的二分和主席树找到询问的是哪个大点中的哪个小点。

在大点上倍增的时候先别跳最后一步,看看跳了之后是不是在同一个大点里,如果是,直接查询小点之间的距离即可。

数组开 n*17 好像有些不够。 n*20 可以。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls Ls[cr]
#define rs Rs[cr]
#define ll long long
using namespace std;
ll rdn()
{
ll ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=1e5+,K=,M=2e6+;//,M=N*K;
int n,m,Q,hd[N],xnt,to[N<<],nxt[N<<],pre[N][K+],dep[N],siz[N];
int h2[N],xt2,t2[N<<],nt2[N<<],pr2[N][K+],dp2[N];
int tim,dfn[N],rt[N],tot,Ls[M],Rs[M],sm[M];
ll s[N],dis[N][K+]; int bin[K+];
struct Node{
int x,y;
Node(int x=,int y=):x(x),y(y) {}
}a[N];
void add(int x,int y){to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;}
void ad2(int x,int y){t2[++xt2]=y;nt2[xt2]=h2[x];h2[x]=xt2;}
void ins(int l,int r,int &cr,int pr,int k)
{
cr=++tot; ls=Ls[pr]; rs=Rs[pr]; sm[cr]=sm[pr]+;
if(l==r)return; int mid=l+r>>;
if(k<=mid)ins(l,mid,ls,Ls[pr],k);
else ins(mid+,r,rs,Rs[pr],k);
}
int qry(int l,int r,int cr,int pr,int k)
{
if(l==r)return l; int mid=l+r>>;
int s=sm[ls]-sm[Ls[pr]];
if(s>=k)return qry(l,mid,ls,Ls[pr],k);
else return qry(mid+,r,rs,Rs[pr],k-s);
}
void ini_dfs(int cr,int fa)
{
siz[cr]=; dep[cr]=dep[fa]+;
dfn[cr]=++tim; ins(,n,rt[tim],rt[tim-],cr);
pre[cr][]=fa;
for(int t=,d;(d=pre[pre[cr][t-]][t-]);t++)
pre[cr][t]=d;
for(int i=hd[cr],v;i;i=nxt[i])
if((v=to[i])!=fa) ini_dfs(v,cr),siz[cr]+=siz[v];
}
int Dis(int x,int y)
{
if(!x||!y)return ; int ret=;//
for(int t=K,lm=dep[x];t>=;t--)
if(dep[pre[y][t]]>=lm)
ret+=bin[t], y=pre[y][t];
return ret;
}
void Ini_dfs(int cr,int fa)
{
dp2[cr]=dp2[fa]+; pr2[cr][]=fa;
dis[cr][]=Dis(a[fa].x,a[cr].y)+;
for(int t=,d;pr2[d=pr2[cr][t-]][t-];t++)
{
pr2[cr][t]=pr2[d][t-];
dis[cr][t]=dis[cr][t-]+dis[d][t-];
}
for(int i=h2[cr],v;i;i=nt2[i])
if((v=t2[i])!=fa) Ini_dfs(v,cr);
}
Node fnd(ll k,int r)
{
int l=,bh=;Node ret;
while(l<=r)
{
int mid=l+r>>;
if(s[mid]>=k)bh=mid,r=mid-;
else l=mid+;
}
ret.x=bh; k-=s[bh-]; bh=a[bh].x;
ret.y=qry(,n,rt[dfn[bh]+siz[bh]-],rt[dfn[bh]-],k);
return ret;
}
int Dis2(int x,int y)
{
int ret=;
if(dep[x]!=dep[y])
{
if(dep[x]<dep[y])swap(x,y);
for(int t=K,lm=dep[y];t>=;t--)
if(dep[pre[x][t]]>=lm)
ret+=bin[t], x=pre[x][t];
}
if(x!=y)
{
for(int t=K;t>=;t--)
if(pre[x][t]!=pre[y][t])
{ ret+=bin[t]<<; x=pre[x][t]; y=pre[y][t];}
ret+=;//
}
return ret;
}
int main()
{
n=rdn();m=rdn();Q=rdn(); ll u,v;
for(int i=;i<n;i++)
u=rdn(),v=rdn(),add(u,v),add(v,u);
bin[]=;for(int i=;i<=K;i++)bin[i]=bin[i-]<<;
ini_dfs(,); tot=;s[]=n;a[]=Node(,); m++;
for(int i=;i<=m;i++)
{
u=rdn();v=rdn();s[i]=s[i-]+siz[u];
Node bh=fnd(v,i-); a[i]=Node(u,bh.y);
ad2(i,bh.x); ad2(bh.x,i);
}
Ini_dfs(,);
for(int i=;i<=Q;i++)
{
u=rdn(); v=rdn(); ll ans=;
Node x=fnd(u,m), y=fnd(v,m);//*.x:blk, *.y:point
if(x.x==y.x){printf("%d\n",Dis2(x.y,y.y));continue;}
if(dp2[x.x]!=dp2[y.x])
{
if(dp2[x.x]<dp2[y.x])swap(x,y);
ans+=Dis(a[x.x].x,x.y);
for(int t=K,lm=dp2[y.x]+;t>=;t--)
if(dp2[pr2[x.x][t]]>=lm)
ans+=dis[x.x][t], x.x=pr2[x.x][t];
if(pr2[x.x][]==y.x)
{printf("%lld\n",ans+Dis2(y.y,a[x.x].y)+);continue;}
ans+=dis[x.x][]; x.x=pr2[x.x][]; x.y=a[x.x].x;
}
ans+=Dis(a[y.x].x,y.y); ans+=Dis(a[x.x].x,x.y);
for(int t=K;t>=;t--)
if(pr2[x.x][t]!=pr2[y.x][t])
{
ans+=dis[x.x][t]+dis[y.x][t];
x.x=pr2[x.x][t]; y.x=pr2[y.x][t];
}
printf("%lld\n",ans+Dis2(a[x.x].y,a[y.x].y)+);
}
return ;
}

bzoj 4539 [Hnoi2016]树——主席树+倍增的更多相关文章

  1. 线段树简单入门 (含普通线段树, zkw线段树, 主席树)

    线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...

  2. BZOJ 4539: [Hnoi2016]树 [主席树 lca]

    4539: [Hnoi2016]树 题意:不想写.复制模板树的子树,查询两点间距离. *** 终于有一道会做的题了...... 画一画发现可以把每次复制的子树看成一个大点来建一棵树,两点的lca一定在 ...

  3. bzoj 4539: [Hnoi2016]树

    Description 小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了.开始,小A只有一棵结点数为N的树,结 点的编号为1,2,-,N,其中结点1为根:我们称这颗树为模板树.小A决定通过 ...

  4. [BZOJ4539][HNOI2016]树(主席树)

    4539: [Hnoi2016]树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 746  Solved: 292[Submit][Status][D ...

  5. bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树

    3545: [ONTAK2010]Peaks Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 635  Solved: 177[Submit][Stat ...

  6. Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)

    3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...

  7. BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)

    换markdown写了.. 题意: 给你一个1e5的字符串,1e5组询问,求\([l_1,r_1]\)的所有子串与\([l_2,r_2]\)的lcp 思路: 首先可以发现答案是具有单调性的,我们考虑二 ...

  8. BZOJ 3524: [Poi2014]Couriers [主席树]

    3524: [Poi2014]Couriers Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1892  Solved: 683[Submit][St ...

  9. bzoj 4012: [HNOI2015]开店 主席树

    Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...

随机推荐

  1. sgu101 欧拉路径 难度:1

    101. Domino time limit per test: 0.25 sec. memory limit per test: 4096 KB Dominoes – game played wit ...

  2. [转载]python的常用代码模板

    URL:http://blog.csdn.net/xingjiarong/article/details/50651235

  3. 【转载】oracle之rowid详解

    原文URL:http://www.2cto.com/database/201109/104961.html 本文讨论的是关于oracle从8i开始引进object的概念后的rowid,即扩展(exte ...

  4. Flask初级(十一)flash与APScheduler 实现定时任务

    from flask import Flask from flask_apscheduler import APScheduler # 引入APScheduler class Config(objec ...

  5. js前台数据校验

    1.脚本 Validator = { exp:{ numWord:/^[A-Za-z0-9]+$/, //数字或字母 numWordM:/^[\-]*[A-Za-z0-9]+$/, //数字或字母可为 ...

  6. java开发的23中设计模式

    本文转自  Java开发中的23种设计模式详解(转)   设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓 ...

  7. avalon 路由问题

    1, 直接使用avalon的 amd加载器, 可以不需要 require.js 2, 配置baseUrl 路径, 这个一定要在 js所在的目录,  而不是jsp所在的目录,  如果js 和jsp分开 ...

  8. MacBook常用软件

    本文分享一些我在mac上的常用软件,也为以后重新配置工作环境做一个记录. 其中提到的大多数软件在网上都有丰富教程,所以仅仅简单描述其功能,不再赘述. 通用 ---Typora Markdown写作工具 ...

  9. QT 5.4.1 for Android Ubuntu QtWebView Demo

    QT 5.4.1 for Android Ubuntu QtWebView Demo 2015-5-15 目录 一.说明: 二.参考文章: 三.QtWebView Demo在哪里? 四.Qt Crea ...

  10. opencv-python教程学习系列9-程序性能检测及优化

    前言 opencv-python教程学习系列记录学习python-opencv过程的点滴,本文主要介绍程序性能检测及优化,坚持学习,共同进步. 系列教程参照OpenCV-Python中文教程: 系统环 ...