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 森林 (可持久化线段树+启发式合并)
题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...
随机推荐
- c++ primer复习(四)
1 标准库容器 顺序容器:vector.list.deque 容器适配器:stack.queue.priority_queue 2 容器元素类型约束: 容器元素类型必须支持复制和赋值,因为容器存放的都 ...
- I/O端口与I/O内存
端口的概念:设备通过系统总线上的接口与CPU相连,接口电路中含有多种寄存器,CPU向设备读写数据实际上是向接口上的寄存器读写数据,这些寄存器称为I/O端口.一个接口通常包含控制端口,数据端口,状态端口 ...
- Chrome浏览器报错:Origin null is not allowed by Access-Control-Allow-Origin.
问题:Chrome浏览器报错:Origin null is not allowed by Access-Control-Allow-Origin. 原因:.js文件中使用load()方法,而Chrom ...
- Spring MVC框架理解
原文链接:ITeye SpringMVC深度探险专栏 基本要素 1. 指定SpringMVC的入口程序(在web.xml中) <!-- Processes application request ...
- CentOS 6.4 使用YUM 安装MySQL5.5
1.首先需要下载Yum的支持包: http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm 2.下载完成后将Yum库导入到你的 ...
- 网易邮箱前端Javascript编码规范:基础规范
在多年开发邮箱webmail过程中,网易邮箱前端团队积累了不少心得体会,我们开发了很多基础js库,实现了大量前端效果组件,开发了成熟的opoa框架以及api组件,在此向大家做一些分享.今天想先和大家聊 ...
- .net线程同步
大家都晓得.NET中线程同步有以下几种方式: 临界区(Critical Section).互斥量(Mutex).信号量(Semaphore).事件(Event) 1.临界区:通过对多线程的串行化来访问 ...
- C语言-06复杂数据类型-01数组
01-数组 #include <stdio.h> int main() { // 使用注意 // 都是正确写法 //int ages[5] = {10 , 11, 12, 67, 56}; ...
- 【转】【Top 100 Best Blogs for iOS Developers】
原文地址:http://www.softwarehow.com/best-blogs-for-ios-developers/ (by JP Zhang | Last updated: Apr 5, 2 ...
- 黑马程序员-------.net基础知识四
常量(静态常量------compile-time) 语法:const 类型 常量名 =常量值: 例: [csharp] view plaincopyprint? { const double PI= ...