主席树的入门题目,这道题的题意其实就是说,给你一棵树,询问在两个节点之间的路径上的区间第K小

我们如何把树上问题转换为区间问题呢?

其实DFS就可以,我们按照DFS的顺序,对线段树进行建树,那么这个树上问题就可以转换为区间问题了,

那么如何询问来表示两个节点之间的路径呢?

其实也很简单,可以看看以下的图。。。

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<algorithm>
#define LL long long
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define per(i,j,k) for(int i=j;i>=k;i--)
#define pb push_back
using namespace std;
const int maxx = ;
struct node{
int l,r,cnt;
}tree[maxx*];
inline int MID(int l,int r){return (l+r)>>;};
int root[maxx*];
int a[maxx];
int ver[maxx*],Next[maxx*],head[maxx];
int tot,cnt,n,m;
int t=;
int fa[maxx],p[maxx][],deepth[maxx];
vector<int>v;
void add(int x,int y){
ver[++tot]=y;Next[tot]=head[x];head[x]=tot;
ver[++tot]=x;Next[tot]=head[y];head[y]=tot;
}
void update(int l,int r,int pre,int &now,int pos){
now=++cnt;
tree[now]=tree[pre];
tree[now].cnt++;
if (l==r)return;
int mid=(l+r)>>;
if (pos<=mid)
update(l,mid,tree[pre].l,tree[now].l,pos);
else
update(mid+,r,tree[pre].r,tree[now].r,pos);
}
int query(int l,int r,int L,int R,int k,int lca,int flac){
if (l==r)return l;
int tmp=tree[tree[R].l].cnt+tree[tree[L].l].cnt-tree[tree[lca].l].cnt-tree[tree[flac].l].cnt;
int mid=MID(l,r);
if (k<=tmp)
return query(l,mid,tree[L].l,tree[R].l,k,tree[lca].l,tree[flac].l);
else
return query(mid+,r,tree[L].r,tree[R].r,k-tmp,tree[lca].r,tree[flac].r);
}
void dfs(int u,int pre){
fa[u]=pre;
deepth[u]=deepth[pre]+;
p[u][]=pre;
update(,n,root[pre],root[u],a[u]);
rep(i,,)p[u][i]=p[p[u][i-]][i-];
for (int i=head[u];i;i=Next[i]){
int y=ver[i];
if (y==pre)continue;
dfs(y,u);
}
}
int LCA(int x,int y){
if (deepth[x]>deepth[y])swap(x,y);
per(i,t,){
if (deepth[p[y][i]]>=deepth[x])y=p[y][i];
}
if (x==y)return y;
per(i,t,){
if(p[x][i]!=p[y][i])x=p[x][i],y=p[y][i];
}
return p[x][];
}
int main(){
while(~scanf("%d%d",&n,&m)){
int uu,vv;
memset(head,,sizeof(head));
rep(i,,n){
scanf("%d",&a[i]);
v.pb(a[i]);
}
tot=;
cnt=;
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
rep(i,,n-){
scanf("%d%d",&uu,&vv);
add(uu,vv);
}
rep(i,,n){
a[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+;
}
dfs(,);
int k;
while(m--){
scanf("%d%d%d",&uu,&vv,&k);
int lca=LCA(uu,vv);
printf("%d\n",v[query(,n,root[uu],root[vv],k,root[lca],root[fa[lca]])-]);
}
}
return ;
}

E - Count on a tree 树上第K小的更多相关文章

  1. spoj COT - Count on a tree (树上第K小 LCA+主席树)

    链接: https://www.spoj.com/problems/COT/en/ 思路: 首先看到求两点之前的第k小很容易想到用主席树去写,但是主席树处理的是线性结构,而这道题要求的是树形结构,我们 ...

  2. Count on a tree 树上主席树

    Count on a tree 树上主席树 给\(n\)个树,每个点有点权,每次询问\(u,v\)路径上第\(k\)小点权,强制在线 求解区间静态第\(k\)小即用主席树. 树上主席树类似于区间上主席 ...

  3. Count on a tree 树上区间第K小

    Count on a tree 题意:求路径 u到v上的 第k小的权重. 题解:先DFS建数, 然后对于每个节点往上跑出一颗主席树, 然后每次更新. 查询的时候, u, v, k, 找到  z = l ...

  4. SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to  ...

  5. SPOJ 10628 Count on a tree(Tarjan离线 | RMQ-ST在线求LCA+主席树求树上第K小)

    COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to  ...

  6. Count on a tree(树上路径第K小)

    题目链接:https://www.spoj.com/problems/COT/en/ 题意:求树上A,B两点路径上第K小的数 思路:主席树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表上. ...

  7. BZOJ 2588: Spoj 10628. Count on a tree [树上主席树]

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MBSubmit: 5217  Solved: 1233 ...

  8. BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

    2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...

  9. 树上第k小,可持久化线段树+倍增lca

    给定一颗树,树的每个结点都有权值, 有q个询问,每个询问是 u v k ,表示u到v路径上第k小的权值是多少. 每个结点所表示的线段树,是父亲结点的线段树添加该结点的权值之后形成的新的线段树 c[ro ...

随机推荐

  1. Slackware网卡配置文件和配置工具

    Slackware 有关网卡的配置文件是/etc/rc.d/rc.inet1.conf , 这个文件包括乙太网接口的网卡和无线网卡的配置.Slackware 还是比较纯净的,网络配置也较简单:在Sla ...

  2. ThinkPHP实现定时执行任务的两种方法 - 博客频道 - CSDN.NET

    在平常的项目中我们总是会遇到需要将某个方法任务定时执行的问题,定时执行方法任务如果我们拥有服务器的权限,我们可以直接在服务器设置定时任务,例如在Windows的任务计划程序中进行设置,在Linux中编 ...

  3. TP5中隐藏入口文件的问题 - CSDN博客

    使用phpstudy和linux部署的时候 tp5中的官方说明是在入口文件的同级目录下添加一个.htaccess文件 文件内容如下: <IfModule mod_rewrite.c>Opt ...

  4. JS---案例:旋转木马

    案例:旋转木马 页面加载时候出现的效果,script标签写在head里面,body上面 显示一个图片散开的动画,遍历之后,把每个图片用封装的动画函数移动到指定目标(同时改变多属性:宽,透明度,层级,t ...

  5. 手把手教你如何玩转消息中间件(ActiveMQ) https://blog.csdn.net/cs_hnu_scw/article/details/81040834

    #情景引入小白:起床起床起床起床....快起床~我:怎么了又,大惊小怪,吓到我了.小白:我有事有事想找你,十万火急呢~~我:你能有什么事?反正我不信..那你说说看~~小白:就是我有两个小表弟,叫大白和 ...

  6. ASP.NET自定义控件组件开发 第一章 第一章:从一个简单的控件谈起

    第一章:从一个简单的控件谈起 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第三 ...

  7. 2018-8-15-WPF-插拔触摸设备触摸失效

    title author date CreateTime categories WPF 插拔触摸设备触摸失效 lindexi 2018-08-15 08:12:47 +0800 2018-08-09 ...

  8. Bellman-Ford(可解决负权边)--时间复杂度优化

    Bellman-Ford 可解决带有负权边的最短路问题 解决负权边和Dijkstra相比是一个优点,Bellman-Ford的核心代码只有4行:: u[],v[],w[] 分别存一条边的顶点.权值,d ...

  9. 【Leetcode 滑动窗口】顺次数(1291)

    题目 我们定义「顺次数」为:每一位上的数字都比前一位上的数字大 1 的整数. 请你返回由 [low, high] 范围内所有顺次数组成的 有序 列表(从小到大排序).   示例 1: 输出:low = ...

  10. 【转】Jython安装(Win)

    ython的安装比较简单,Jython的安装程序本身就是一个Java应用程序,因此,在安装之前,你必须具备Java运行的环境.下面以 Jython的Jython2.2.1为例,说明Jython的安装步 ...