Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
第二行N个整数,v[1]~v[n],代表每个节点的权值。
接下来N-1行每行两个整数x,y代表x和y有一条边
最后M行每行三个整数a,b,c,表示一组询问。
1 3 2 4 5
1 2
2 4
4 3
4 5
1 1 5
2 1 3
3 1 5
4
4
数据1~3 N,M<=1000
数据4~6 N,M<=5000
数据7~10 N,M<=10000
数据11~18 N,M<=30000
数据19~20 N,M<=100000
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
struct node
{
int begin,end,next;
}edge[MAXN*];
struct NODE
{
int left,right;
}tree[MAXN*];
int cnt,Head[MAXN],SIZE,deep[MAXN],P[MAXN][],tot,root[MAXN],n,sum[MAXN*],val[MAXN],cc[MAXN],pos[MAXN],value[MAXN];
bool vis[MAXN];
void addedge(int bb,int ee)
{
edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
}
void addedge1(int bb,int ee)
{
addedge(bb,ee);addedge(ee,bb);
}
int read()
{
int s=,fh=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')fh=-;ch=getchar();}
while(ch>=''&&ch<=''){s=s*+(ch-'');ch=getchar();}
return s*fh;
}
void dfs(int u)
{
int i,v;
vis[u]=true;
SIZE++;pos[u]=SIZE;value[SIZE]=u;
for(i=Head[u];i!=-;i=edge[i].next)
{
v=edge[i].end;
if(vis[v]==false)
{
deep[v]=deep[u]+;
P[v][]=u;
dfs(v);
}
}
}
void Ycl()
{
int i,j;
for(j=;(<<j)<=n;j++)
{
for(i=;i<=n;i++)
{
if(P[i][j-]!=-)P[i][j]=P[P[i][j-]][j-];
}
}
}
int LCA(int x,int y)
{
if(deep[x]<deep[y])swap(x,y);
int i,j;
for(i=;(<<i)<=deep[x];i++);i--;
for(j=i;j>=;j--)if(deep[x]-(<<j)>=deep[y])x=P[x][j];
if(x==y)return x;
for(j=i;j>=;j--)
{
if(P[x][j]!=-&&P[x][j]!=P[y][j])
{
x=P[x][j];
y=P[y][j];
}
}
return P[x][];
}
void Build(int x,int &y,int l,int r,int B)
{
y=++SIZE;
sum[y]=sum[x]+;
if(l==r)return;
tree[y].left=tree[x].left;tree[y].right=tree[x].right;
int mid=(l+r)/;
if(B<=mid)Build(tree[x].left,tree[y].left,l,mid,B);
else Build(tree[x].right,tree[y].right,mid+,r,B);
}
int Query(int l,int r,int A,int B,int C,int D,int Q)
{
if(l==r)return l;
int mid,delta=sum[tree[A].left]+sum[tree[B].left]-sum[tree[C].left]-sum[tree[D].left];
mid=(l+r)/;
if(Q<=delta)return Query(l,mid,tree[A].left,tree[B].left,tree[C].left,tree[D].left,Q);
else return Query(mid+,r,tree[A].right,tree[B].right,tree[C].right,tree[D].right,Q-delta);
}
int query(int u,int v,int lca,int k)
{
int A=pos[u],B=pos[v],C=pos[lca],D=pos[P[lca][]];
return Query(,tot,root[A],root[B],root[C],root[D],k);
}
int main()
{
int m,i,wz,s1,s2,s3,lca,k,bb,ee;
n=read();m=read();
for(i=;i<=n;i++)val[i]=read(),cc[i]=val[i];
sort(cc+,cc+n+);
tot=unique(cc+,cc+n+)-(cc+);
memset(Head,-,sizeof(Head));cnt=;
for(i=;i<n;i++){bb=read();ee=read();addedge1(bb,ee);}
memset(P,-,sizeof(P));
SIZE=;
dfs();Ycl();
SIZE=;
for(i=;i<=n;i++)//按树上顺序插入.
{
k=value[i];
wz=lower_bound(cc+,cc+tot+,val[k])-cc;
Build(root[pos[P[k][]]],root[i],,tot,wz);
}
SIZE=;
for(i=;i<=m;i++)
{
s1=read();s2=read();s3=read();
if(s1==){lca=LCA(s2,s3);printf("%d\n",cc[query(s2,s3,lca,)]);}
else if(s1==){lca=LCA(s2,s3);k=deep[s2]+deep[s3]-*deep[lca]+;printf("%d\n",cc[query(s2,s3,lca,k)]);}
else {lca=LCA(s2,s3);k=(deep[s2]+deep[s3]-*deep[lca]+)/;printf("%d\n",cc[query(s2,s3,lca,k)]);}
}
fclose(stdin);
fclose(stdout);
return ;
}
Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序的更多相关文章
- 【bzoj2653】middle 可持久化线段树区间合并
题目描述 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整.给你一个长度为n的序列s.回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[ ...
- ACM学习笔记:可持久化线段树
title : 可持久化线段树 date : 2021-8-18 tags : 数据结构,ACM 可持久化线段树 可以用来解决线段树存储历史状态的问题. 我们在进行单点修改后,线段树只有logn个(一 ...
- BZOJ - 2588 Spoj 10628. Count on a tree (可持久化线段树+LCA/树链剖分)
题目链接 第一种方法,dfs序上建可持久化线段树,然后询问的时候把两点之间的所有树链扒出来做差. #include<bits/stdc++.h> using namespace std; ...
- [HNOI2016]树(可持久化线段树+树上倍增)
[HNOI2016]树(可持久化线段树+树上倍增) 题面 给出一棵n个点的模板树和大树,根为1,初始的时候大树和模板树相同.接下来操作m次,每次从模板树里取出一棵子树,把它作为新树里节点y的儿子.操作 ...
- BZOJ4771七彩树——可持久化线段树+set+树链的并+LCA
给定一棵n个点的有根树,编号依次为1到n,其中1号点是根节点.每个节点都被染上了某一种颜色,其中第i个节 点的颜色为c[i].如果c[i]=c[j],那么我们认为点i和点j拥有相同的颜色.定义dept ...
- 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径
51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...
- BZOJ 2588: Spoj 10628. Count on a tree-可持久化线段树+LCA(点权)(树上的操作) 无语(为什么我的LCA的板子不对)
2588: Spoj 10628. Count on a tree Time Limit: 12 Sec Memory Limit: 128 MBSubmit: 9280 Solved: 2421 ...
- [IOI2018]狼人——kruskal重构树+可持久化线段树
题目链接: IOI2018werewolf 题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态 ...
- BZOJ - 3123 森林 (可持久化线段树+启发式合并)
题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...
随机推荐
- 九度OJ 1113 二叉树
题目地址:http://ac.jobdu.com/problem.php?pid=1113 题目描述: 如上所示,由正整数1,2,3……组成了一颗特殊二叉树.我们已知这个二叉树的最后一个结点是n.现在 ...
- spring setter方法注入
<bean id="dao" class="Dao"></bean> <bean id="service" c ...
- nginx 自定义代理返回 404
在nginx的http段,加上一面的配置 proxy_intercept_errors on;//自定义代理返回的404错误提示
- php文件锁解决少量并发问题
阻塞(等待)模式: <?php $fp = fopen("lock.txt", "r"); if(flock($fp,LOCK_EX)) { //..处理 ...
- onbeforeunload、beforeunload
<script type="text/javascript"> function addOnBeforeUnload(e) { var ev = e || ev ...
- luarocks在macOS系统上的安装
luarocks是基于lua开发的一个包管理工具,所以在安装luarocks之前需要先安装lua(见博客同目录下“lua在MacOS系统上的安装”).具体的安装步骤如下: 1.源码安装部署luaroc ...
- POJ 2299 Ultra-QuickSort 归并排序、二叉排序树,求逆序数
题目链接: http://poj.org/problem?id=2299 题意就是求冒泡排序的交换次数,显然直接冒泡会超时,所以需要高效的方法求逆序数. 利用归并排序求解,内存和耗时都比较少, 但是有 ...
- a href="#"与a href="####"的区别是什么
前提是 :有滚动条. [感谢 黎明就在眼前 博客园园友] '#' 是有特殊意义,如果 '#' 后有内容会被认为是一个标签而从页面找到相应标签跳转到该处,找不到时会跳到页首,通常情况下使用“#ID”来 ...
- 多目标遗传算法 ------ NSGA-II (部分源码解析)状态报告 打印 report.c
/* Routines for storing population data into files */ # include <stdio.h> # include <stdlib ...
- C#中的委托事件的分析
推荐:http://www.cnblogs.com/SkySoot/archive/2012/04/05/2433639.html 委托和事件在 .NET Framework 中的应用非常广泛,然而, ...