【传送门:caioj1443


简要题意:

  给出一颗n个点的树,给出每个点的权值,再给出n-1条边,有m个询问,每个询问输入x,y,k,输出第x节点到第y节点的路径上第k大的点


题解:

  这是一道主席树的例题,感觉很想用树链剖分,但是会超时吧......

  做法就是将每个点到树的根所形成的链建立线段树,然后dfs找出点与点之间的父子关系,每个点都将自己和自己的父亲,自己的父亲的父亲....直到根所组成的所有线段树合并起来,然后就可以得到能够代表区间的主席树了,然后每当询问输入x,y时,就先找x和y的最近公共祖先(倍增LCA来求),然后x和y的路径其实就是x到根的路径加上y到根的路径,然后减去最近公共祖先到根的路径,再减去最近公共祖先的父亲到根的路径(为什么是最近公共祖先的父亲呢,因为如果是再减去最近公共祖先到根的路径的话,最近公共祖先就会被除去,这样是不对的,所以减去最近公共祖先的父亲到根的路径)


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
int s[],ss[];
struct trnode
{
int lc,rc,c;
}tr[];int cnt;
int rt[];
struct edge
{
int x,y,next;
}a[];int len,last[];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
int n;
int LS(int d)
{
int l=,r=n,ans=;
while(l<=r)
{
int mid=(l+r)/;
if(s[mid]<=d)
{
ans=mid;
l=mid+;
}
else r=mid-;
}
return ans;
}
void Link(int &u,int l,int r,int p)
{
if(u==) u=++cnt;
tr[u].c++;
if(l==r) return ;
int mid=(l+r)/;
if(p<=mid) Link(tr[u].lc,l,mid,p);
else Link(tr[u].rc,mid+,r,p);
}
void Merge(int &u1,int u2)
{
if(u1==){u1=u2;return ;}
if(u2==) return ;
tr[u1].c+=tr[u2].c;
Merge(tr[u1].lc,tr[u2].lc);
Merge(tr[u1].rc,tr[u2].rc);
}
int dep[];
int f[][];
int LCA(int x,int y)
{
if(dep[x]<dep[y]) swap(x,y);
for(int i=;i>=;i--) if(dep[x]-dep[y]>=(<<i)) x=f[x][i];
if(x==y) return x;
for(int i=;i>=;i--)
if(dep[x]>=(<<i)&&f[x][i]!=f[y][i])
{
x=f[x][i];y=f[y][i];
}
return f[x][];
}
void bt(int x,int fa)
{
dep[x]=dep[fa]+;
f[x][]=fa;
for(int i=;(<<i)<=dep[x];i++) f[x][i]=f[f[x][i-]][i-];
Merge(rt[x],rt[fa]);
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa)
{
bt(y,x);
}
}
}
int Ask(int u1,int u2,int u3,int u4,int l,int r,int p)
{
if(l==r) return s[l];
int c=tr[tr[u1].lc].c+tr[tr[u2].lc].c-tr[tr[u3].lc].c-tr[tr[u4].lc].c;
int mid=(l+r)/;
if(p<=c) return Ask(tr[u1].lc,tr[u2].lc,tr[u3].lc,tr[u4].lc,l,mid,p);
else return Ask(tr[u1].rc,tr[u2].rc,tr[u3].rc,tr[u4].rc,mid+,r,p-c);
}
int main()
{
int m;
scanf("%d%d",&n,&m);
cnt=;memset(rt,,sizeof(rt));
for(int i=;i<=n;i++)
{
scanf("%d",&ss[i]);
s[i]=ss[i];
}
sort(s+,s+n+);
len=;memset(last,,sizeof(last));
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ins(x,y);ins(y,x);
}
cnt=;
for(int i=;i<=n;i++) Link(rt[i],,n,LS(ss[i]));
dep[]=;bt(,);
for(int i=;i<=m;i++)
{
int x,y,k;
scanf("%d%d%d",&x,&y,&k);
int lca=LCA(x,y);
printf("%d\n",Ask(rt[x],rt[y],rt[lca],rt[f[lca][]],,n,k));
}
return ;

caioj1443:第k小的数Ⅲ的更多相关文章

  1. *HDU2852 树状数组(求第K小的数)

    KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  2. 计算序列中第k小的数

    作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046399.html 使用分治算法,首先选择随机选择轴值pivot,并使的序列中比pivot ...

  3. [LeetCode] Find K-th Smallest Pair Distance 找第K小的数对儿距离

    Given an integer array, return the k-th smallest distance among all the pairs. The distance of a pai ...

  4. #7 找出数组中第k小的数

    「HW面试题」 [题目] 给定一个整数数组,如何快速地求出该数组中第k小的数.假如数组为[4,0,1,0,2,3],那么第三小的元素是1 [题目分析] 这道题涉及整数列表排序问题,直接使用sort方法 ...

  5. 无序数组求第k大/第k小的数

    根据http://www.cnblogs.com/zhjp11/archive/2010/02/26/1674227.html 博客中所总结的7种解法,我挑了其中的解法3和解法6进行了实现. 解法3: ...

  6. 查找第K小的数 BFPRT算法

    出处 http://blog.csdn.net/adong76/article/details/10071297 BFPRT算法是解决从n个数中选择第k大或第k小的数这个经典问题的著名算法,但很多人并 ...

  7. 基于快速排序思想partition查找第K大的数或者第K小的数。

    快速排序 下面是之前实现过的快速排序的代码. function quickSort(a,left,right){ if(left==right)return; let key=partition(a, ...

  8. 算法---数组总结篇2——找丢失的数,找最大最小,前k大,第k小的数

    一.如何找出数组中丢失的数 题目描述:给定一个由n-1个整数组成的未排序的数组序列,其原始都是1到n中的不同的整数,请写出一个寻找数组序列中缺失整数的线性时间算法 方法1:累加求和 时间复杂度是O(N ...

  9. cogs930找第k小的数(k-th number)

    cogs930找第k小的数(k-th number) 原题链接 题解 好题... 终极版是bzoj3065(然而并不会) 先讲这个题... 维护\(n+1\)个值域线段树(用主席树),标号\(0\) ...

随机推荐

  1. [HAOI2016]找相同字符(SAM+DP)

    感觉很水. 因为SAM上一个点的子树大小代表这个点所表示子串的出现次数. 建出广义后缀自动机之后.在\(parent\)树上跑\(DP\),维护\(size[i][1]\),和\(size[i][0] ...

  2. 洛谷 P1052 过河 (离散化+dp)

    dp非常好想, f[i] = min(f[i-len] + stone[i]) s <= len <= t 然后因为L非常大,所以我就不知道该怎么搞了 我看到m只有100,而L有1e9,我 ...

  3. WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配

    原文:WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配 WPF Toolkit AutoCompleteBox 实体类绑定 关键字自定义关联搜索匹配 网上的 ...

  4. 【codeforces 314C】Sereja and Subsequences

    [题目链接]:http://codeforces.com/problemset/problem/314/C [题意] 让你从n个元素的数组中选出所有的不同的非递减子数列; 然后计算比这个子数列小的和它 ...

  5. wget 升级

    漏洞描述: Wget是GNU计划开发的一套用于在网络上进行下载的自由软件,是Unix/Linux系统最常用的下载工具,支持通过HTTP.HTTPS以及FTP这三个最常见的TCP/IP协议下载. Wge ...

  6. ADT+NDK搭建jni编译环境

    jni是android调用C++编写的库的接口.C++和java的差别不在此文的讨论范畴,另外这里也仅仅是记录下.怎样搭建好开发环境. 首先是下载ADT包和NDK包. ADT包包括了eclipse.所 ...

  7. hadoop-07-ntp服务检查

    hadoop-07-ntp服务检查 cd /etc/more /etc/ntp.conf里面进行了server的配置 service ntpd status / stop/ start 安装ntpd ...

  8. hdu 4841 圆桌问题(用vector模拟约瑟夫环)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4841 圆桌问题 Time Limit: 3000/1000 MS (Java/Others)    M ...

  9. IOS开发-经常使用站点集合

    1.    https://developer.apple.com  //苹果开发人员站点 2.    https://itunesconnect.apple.com  //itunes站点 3.   ...

  10. Irrlicht 3D Engine 笔记系列 之 教程6- 2D Graphics

    作者:i_dovelemon 日期:2015 / 7 / 1 来源: CSDN 主题:2D Graphics, Irrlicht 教程翻译 本篇教程将要向大家展示怎样使用Irrlicht引擎绘制2D图 ...