Time Limit: 129MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu

Submit Status

Description

You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight.

We will ask you to perform the following operation:

  • u v k : ask for the kth minimum weight on the path from node u to node v

Input

In the first line there are two integers N and M.(N,M<=100000)

In the second line there are N integers.The ith integer denotes the weight of the ith node.

In the next N-1 lines,each line contains two integers u v,which describes an edge (u,v).

In the next M lines,each line contains three integers u v k,which means an operation asking for the kth minimum weight on the path from node u to node v.

Output

For each operation,print its result.

Example

Input:
8 5
8 5
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
2 5 2
2 5 3
2 5 4
7 8 2 
Output:
2
8
9
105

题意:求树上的边[u,v]中点权第k大

使用的是主席树+LCA(RMQ.dfs),然后去专门看了下RMQ+dfs实现LCA

用一个数组记录深度,然后记录搜索的路径,如果要找[a,b]中的LCA,直接找[a,b]中的深度最小值即可

参考:算法之LCA与RMQ问题

/*
主席树-代码参考kuangbin大神
在本题中相当于按树的节点来构建线段树,每个节点基于它的父亲进行构建
然后节点a保存的便是根到a的情况,于是乎我们T[a]+T[b]-2*T[lca(a,b)]即可
而且对lca节点进行一个判断。
hhh-2016-02-18 21:11:14
*/ #include <functional>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
using namespace std; const int maxn = 200010;
int n,m;
int a[maxn],t[maxn];
int T[maxn*40],val[maxn*40],lson[maxn*40],rson[maxn*40];
int Tot; void ini_hash() //排序去重
{
for(int i =1; i <= n; i++)
t[i] = a[i];
sort(t+1,t+n+1);
m = unique(t+1,t+n+1)-t-1;
} int Hash(int x) //获得x在排序去重后的位置
{
return lower_bound(t+1,t+m+1,x) - t;
} int build(int l,int r)
{
int root = Tot++;
val[root] = 0;
if(l != r)
{
int mid = (l+r)>>1;
lson[root] = build(l,mid);
rson[root] = build(mid+1,r);
}
return root;
} //如果那里发生改变则兴建一个节点而非像平常修改那个节点的值
int update(int root,int pos,int va)
{
int newroot = Tot++;
int tmp = newroot;
val[newroot] = val[root] + va;
int l = 1,r = m;
while(l < r)
{
int mid = (l+r)>>1;
if(pos <= mid)
{
lson[newroot] = Tot++;
rson[newroot] = rson[root];
newroot = lson[newroot];
root = lson[root];
r = mid;
}
else
{
lson[newroot] = lson[root];
rson[newroot] = Tot++;
newroot = rson[newroot];
root = rson[root];
l = mid+1;
}
val[newroot] = val[root] + va;
}
return tmp;
} int query(int lt,int rt,int lca,int k)
{
int lca_rt = T[lca];
int pos = Hash(a[lca]);
int l = 1, r = m;
while(l < r)
{
int mid = (l+r)>>1;
int tmp = val[lson[lt]]+val[lson[rt]]-2*val[lson[lca_rt]]+(pos>=l&&pos<=mid);
if(tmp >= k)
{
lt = lson[lt];
rt = lson[rt];
lca_rt = lson[lca_rt];
r = mid;
}
else
{
k -= tmp;
l = mid+1;
lt = rson[lt];
rt = rson[rt];
lca_rt = rson[lca_rt];
}
}
return l;
} int rmq[maxn*2]; //表示深度
struct ST
{
int mm[maxn*2];
int dp[maxn*2][20];
void ini(int n)
{
mm[0] = -1;
for(int i = 1; i <= n; i++)
{
mm[i] = ((i&(i-1)) == 0)?mm[i-1]+1:mm[i-1];
dp[i][0] = i;
}
for(int j = 1; j <= mm[n]; j++)
for(int i = 1; i + (1<<j) - 1 <= n; i++)
dp[i][j] = rmq[dp[i][j-1]] < rmq[dp[i+(1<<(j-1))][j-1]]?
dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
}
int query(int a,int b)
{
if(a > b)swap(a,b);
int k = mm[b-a+1];
return rmq[dp[a][k]] <= rmq[dp[b-(1<<k)+1][k]]?
dp[a][k]:dp[b-(1<<k)+1][k];
}
}; struct E
{
int to,next;
} edge[maxn*2];
int tot,head[maxn];
int F[maxn*2];
int P[maxn];
int cnt;
//F表示dfs的序列
//P[i]表示i第一次出现的位置 ST st;
void init() //初始化
{
Tot = tot = 0;
memset(head,-1,sizeof(head));
} void dfs(int u,int pre,int dep)
{
F[++cnt] = u;
rmq[cnt] = dep;
P[u] = cnt;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == pre)continue;
dfs(v,u,dep+1);
F[++cnt] = u;
rmq[cnt] = dep;
}
} void ini_lca(int root,int num)
{
cnt = 0;
dfs(root,root,0);
st.ini(2*num-1);
} void addedge(int u,int v)
{
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
} int query_lca(int u,int v)
{
return F[st.query(P[u],P[v])];
} void dfs_build(int u,int pre)
{
int pos = Hash(a[u]);
T[u] = update(T[pre],pos,1);
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == pre) continue;
dfs_build(v,u);
}
} int main()
{
int q;
while(scanf("%d%d",&n,&q) == 2)
{
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
ini_hash();
init();
int u,v,k;
for(int i = 1; i < n; i++)
{ scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
ini_lca(1,n);
T[n+1] = build(1,m);
dfs_build(1,n+1);
while(q--)
{
scanf("%d%d%d",&u,&v,&k);
printf("%d\n",t[query(T[u],T[v],query_lca(u,v),k)]);
}
}
return 0;
}

  

SPOJ COT(树上的点权第k大)的更多相关文章

  1. LCA+主席树 (求树上路径点权第k大)

      SPOJ 10628. Count on a tree (树上第k大,LCA+主席树) 10628. Count on a tree Problem code: COT You are given ...

  2. Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)

    题目链接:https://www.spoj.com/problems/COT/en/ 题目: 题意: 给你一棵有n个节点的树,求节点u到节点v这条链上的第k大. 思路: 我们首先用dfs进行建题目给的 ...

  3. SPOJ Lexicographical Substring Search 求字典序第k大子串 后缀自动机

    题目传送门 思路:按字典序,小的字符优先选取.对于一个字符,如果以这个字符开头的子串大于等于k个,那说明这个字符是应该选的,并且选完之后,可能还要继续选.如果以这个字符开头的子串小于k个,说明这个字符 ...

  4. 【学术篇】SPOJ COT 树上主席树

    这是学完主席树去写的第二道题_(:з」∠)_ 之前用树上莫队水过了COT2... 其实COT也可以用树上莫队水过去不过好像复杂度要带个log还是怎么样可能会被卡常数.. 那就orz主席吧.... 写了 ...

  5. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  6. 主席树——树链上第k大spoj COT

    首先要求第k大就想到用主席树来处理 但是不能直接用树链剖分的dfs序来维护,因为一条链对应的dfs下标可能是断开的几段,无法用权值线段树来维护 那么久维护每个点到根节点的全值线段树,结点u的权值线段树 ...

  7. SPOJ - COT Count on a tree

    地址:http://www.spoj.com/problems/COT/en/ 题目: COT - Count on a tree #tree You are given a tree with N  ...

  8. bzoj 3784: 树上的路径 堆维护第k大

    3784: 树上的路径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 88  Solved: 27[Submit][Status][Discuss] ...

  9. HDU 4729 An Easy Problem for Elfness (主席树,树上第K大)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意:给出一个带边权的图.对于每一个询问(S , ...

随机推荐

  1. "未找到应用程序的“aps-environment”的权利字符串"

    1.先生成App ID,在去Provisioning里面生成新的Profile 2.删除Xcode里面原来的push profile(如果没有就不用删除)再次双击新下载的profile(mobilep ...

  2. 进军ABP第一天:ABP理论知识

    1.2.3 领域层领域层就是业务层,是一个项目的核心,所有业务规则都应该在领域层实现. ( 实体(Entity ) 实体代表业务领域的数据和操作,在实践中,通过用来映射成数据库表. ( 仓储(Repo ...

  3. python安装及写一个简单的验证码组件(配合node)

    1.安装Python 到官网下载响应系统的版本(这里以windows为例):https://www.python.org/downloads/windows/ 然后就是不断地"下一步&quo ...

  4. Mego开发文档 - 索引

    Mego 开发文档 Mego 快速概述 主要特性 获取Mego 使用流程 模型 查询 保存数据 入门 Mego 快速开始 创建项目 安装Nuget包 创建连接字符串 创建模型及数据上下文(添加引用) ...

  5. OAuth2.0学习(1-6)授权方式3-密码模式(Resource Owner Password Credentials Grant)

    授权方式3-密码模式(Resource Owner Password Credentials Grant) 密码模式(Resource Owner Password Credentials Grant ...

  6. Python之编码

    一.Python2与Python3的区别 1.从宏观上考虑,Python2重复代码太多,错误率高,不够规范.Python崇尚的是语言简洁.优美.清晰.Python3更加规范,重复代码少: 2.Pyth ...

  7. jscript定时器,一直用的东西,你真的明白吗?

    JavaScript定时器 JavaScript是一种解释型语言(边编译边执行),Js解析顺序是从上到下,然后将编译后的任务丢到一个事件队列中,然后事件内的函数会从上到下开始执行 setInterva ...

  8. java Hibernate 处理 oracle xmltype类型

    网上关于如何处理oracle xmltype类型的博客很多,我现在分享的是针对具体业务来的,我在oracle数据库entity表中detail插入了一条xmltype类型的数据 xml的详细内容如下: ...

  9. 算法 排序lowB三人组 冒泡排序 选择排序 插入排序

    参考博客:基于python的七种经典排序算法   [经典排序算法][集锦]     经典排序算法及python实现 首先明确,算法的实质 是 列表排序.具体就是操作的列表,将无序列表变成有序列表! 一 ...

  10. angular中的路径问题

    我们在写项目时会遇到启动页调到引导页,引导页再调到首页, 那我们在用angular框架写这种东西的时候如果我们不细心的话就会遇到问题, 比如说找不到引导页的图片等等. 那我们怎么解决这个问题呢? 首先 ...