bzoj 4539 [Hnoi2016]树——主席树+倍增
题目: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]树——主席树+倍增的更多相关文章
- 线段树简单入门 (含普通线段树, zkw线段树, 主席树)
线段树简单入门 递归版线段树 线段树的定义 线段树, 顾名思义, 就是每个节点表示一个区间. 线段树通常维护一些区间的值, 例如区间和. 比如, 上图 \([2, 5]\) 区间的和, 为以下区间的和 ...
- BZOJ 4539: [Hnoi2016]树 [主席树 lca]
4539: [Hnoi2016]树 题意:不想写.复制模板树的子树,查询两点间距离. *** 终于有一道会做的题了...... 画一画发现可以把每次复制的子树看成一个大点来建一棵树,两点的lca一定在 ...
- bzoj 4539: [Hnoi2016]树
Description 小A想做一棵很大的树,但是他手上的材料有限,只好用点小技巧了.开始,小A只有一棵结点数为N的树,结 点的编号为1,2,-,N,其中结点1为根:我们称这颗树为模板树.小A决定通过 ...
- [BZOJ4539][HNOI2016]树(主席树)
4539: [Hnoi2016]树 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 746 Solved: 292[Submit][Status][D ...
- bzoj 3545&&3551: [ONTAK2010]Peaks &&加强版 平衡树&&并查集合并树&&主席树
3545: [ONTAK2010]Peaks Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 635 Solved: 177[Submit][Stat ...
- Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...
- BZOJ 4556(后缀数组+主席树求前驱后继+二分||后缀数组+二分+可持久化线段树)
换markdown写了.. 题意: 给你一个1e5的字符串,1e5组询问,求\([l_1,r_1]\)的所有子串与\([l_2,r_2]\)的lcp 思路: 首先可以发现答案是具有单调性的,我们考虑二 ...
- BZOJ 3524: [Poi2014]Couriers [主席树]
3524: [Poi2014]Couriers Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1892 Solved: 683[Submit][St ...
- bzoj 4012: [HNOI2015]开店 主席树
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
随机推荐
- ORACLE workflow审批界面显示附件信息和附件的下载链接(转)
原文: ORACLE workflow审批界面显示附件信息和附件的下载链接 EBS获取附件URL 代码如下: CREATE OR REPLACE PACKAGE cux_attachment_util ...
- oracle EBS grant 您不具有执行当前操作的足够权限。请与您的系统管理员联系。
解决方式1: Set the profiles of the below three to 'None' 设置以下三个配置文件为无 FND_VALIDATION_LEVELFND 验证层 FND_FU ...
- DB2性能调优
1.更新统计信息 --更新数据库所有表统计信息 --连接到数据库(-v选项,表示要回显命令,以下同) db2 -v connect to DB_NAME --查看是否收集过统计信息,什么时候更新的 ...
- jw
1. ISO/OSI参考模型(七层) 应表会传 传输介质(双绞线,同轴电缆等)不在OSI7个层次之内 电气特性:电压表示0,1: 机械特性:接口形状,尺寸等 过程特性:出现顺序及信号线的工作原理 ...
- 2.strcpy使用注意(2)
分析下述代码: void test2() { char string[10],str1[10]; int i; for(i=0;i<10;i++) { srtr1='a'; } strcpy(s ...
- 51nod算法马拉松28-c
题解: 按照每一个要求,分类讨论,讨论压下去了多少 代码: #include<bits/stdc++.h> using namespace std; ,N=; int n,A,B,C,an ...
- CCF CSP 201703
CCF CSP 2017·03 做了一段时间的CCF CSP试题,个人感觉是这样分布的 A.B题基本纯暴力可满分 B题留心数据范围 C题是个大模拟,留心即可 D题更倾向于图论?(个人做到的D题基本都是 ...
- html内容滚动
<marquee srolldelay="50" direction="up"></marquee> 滚动标签<marquee&g ...
- SaltStack自动化运维工具
一.SaltStack的了解 SaltStack管理工具允许管理员对多个操作系统创建一个一致的管理系统,包括VMware vSphere环境. SaltStack作用于仆从和主拓扑.SaltStack ...
- anu - controlledComponent
/** input, select, textarea这几个元素如果指定了value/checked的**状态属性**,就会包装成受控组件或非受控组件 受控组件是指,用户除了为它指定**状态属性**, ...