caioj1443:第k小的数Ⅲ
【传送门: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小的数Ⅲ的更多相关文章
- *HDU2852 树状数组(求第K小的数)
KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- 计算序列中第k小的数
作者:jostree 转载请注明出处 http://www.cnblogs.com/jostree/p/4046399.html 使用分治算法,首先选择随机选择轴值pivot,并使的序列中比pivot ...
- [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 ...
- #7 找出数组中第k小的数
「HW面试题」 [题目] 给定一个整数数组,如何快速地求出该数组中第k小的数.假如数组为[4,0,1,0,2,3],那么第三小的元素是1 [题目分析] 这道题涉及整数列表排序问题,直接使用sort方法 ...
- 无序数组求第k大/第k小的数
根据http://www.cnblogs.com/zhjp11/archive/2010/02/26/1674227.html 博客中所总结的7种解法,我挑了其中的解法3和解法6进行了实现. 解法3: ...
- 查找第K小的数 BFPRT算法
出处 http://blog.csdn.net/adong76/article/details/10071297 BFPRT算法是解决从n个数中选择第k大或第k小的数这个经典问题的著名算法,但很多人并 ...
- 基于快速排序思想partition查找第K大的数或者第K小的数。
快速排序 下面是之前实现过的快速排序的代码. function quickSort(a,left,right){ if(left==right)return; let key=partition(a, ...
- 算法---数组总结篇2——找丢失的数,找最大最小,前k大,第k小的数
一.如何找出数组中丢失的数 题目描述:给定一个由n-1个整数组成的未排序的数组序列,其原始都是1到n中的不同的整数,请写出一个寻找数组序列中缺失整数的线性时间算法 方法1:累加求和 时间复杂度是O(N ...
- cogs930找第k小的数(k-th number)
cogs930找第k小的数(k-th number) 原题链接 题解 好题... 终极版是bzoj3065(然而并不会) 先讲这个题... 维护\(n+1\)个值域线段树(用主席树),标号\(0\) ...
随机推荐
- 一片非常有趣的文章 三分钟读懂TT猫分布式、微服务和集群之路
原文http://www.cnblogs.com/smallSevens/p/7501932.html#3782600 三分钟读懂TT猫分布式.微服务和集群之路 针对新手入门的普及,有过大型网站技 ...
- 紫书 习题 11-3 UVa 820 (最大流裸题)
注意这道题是双向边, 然后直接套模板就ok了. #include<cstdio> #include<algorithm> #include<vector> #inc ...
- [luogu]P4364 [九省联考2018]IIIDX
题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了. 这款音乐 ...
- hbase报错Could not initialize class org.apache.hadoop.hbase.protobuf.ProtobufUtil
Caused by: java.lang.RuntimeException: java.io.IOException: java.lang.reflect.InvocationTargetExcept ...
- HDU 4704 Sum Fermat定律
Problem Description Sample Input 2 Sample Output 2 Hint 1. For N = 2, S(1) = S(2) = 1. 2. The in ...
- Android Studio生成apk
1.菜单Build->Generate Signed APK 2.生成android.keystore,能够依据弹框去Create new一个,也可使用命令来生成android.keystore ...
- RabbitMQserver配置文件
RabbitMQ的server配置设置.我做了改动,改动例如以下: {tcp_listeners, [5672]}, {loopback_users, ["elite"]} 其他的 ...
- 走进windows编程的世界-----消息处理函数(2)
一 WM_PAINT消息 1 WM_PAINT的产生 因为窗体的互相覆盖等,产生须要绘制的区域,那么会产生WM_PAINT消息. 普通情况下,不直接发送WM_PAINT消息,通过API声明须要 ...
- nyoj--1011--So Easy[II](数学几何水题)
So Easy[II] 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 这是一道基础的计算几何问题(其实这不提示大家也都看的出).问题描述如下: 给你一个N边形.且N边形 ...
- Linux-php安装mongodb
Linux-php安装mongodb 标签(空格分隔): php 安装mongodb 1 下载解压 下载压缩包 :https://www.mongodb.com/download-center?jmp ...