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. pickle使用及案例

    一.字典格式数据源写入数据库文件 #!/usr/bin/env python # -*- coding:utf-8 -*- import pickle accounts ={1000:'alex', ...

  2. Python 迭代器之列表解析

     [TOC] 尽管while和for循环能够执行大多数重复性任务, 但是由于序列的迭代需求如此常见和广泛, 以至于Python提供了额外的工具以使其更简单和高效. 迭代器在Python中是以C语言的 ...

  3. 服务器数据恢复_服务器xfs数据丢失数据恢复

    简介:太原一家公司的服务器出现故障,服务器是linux服务器,连接了一台某型号的存储,文件系统为xfs文件系统.管理员使用xfs_repair工具试图对文件系统进行修复但修复失败,linux服务器中所 ...

  4. 成功案例分享:raid5两块硬盘掉线数据丢失恢复方法

    1. 故障描述    本案例是HP P2000的存储vmware exsi虚拟化平台,由RAID-5由10块lT硬盘组成,其中6号盘是热备盘,由于故障导致RAID-5磁盘阵列的两块盘掉线,表现为两块硬 ...

  5. PM2使用心得

    PM2是node进程管理工具,可以利用它来简化很多node应用管理的繁琐任务,如性能监控.自动重启.负载均衡等,而且使用非常简单. 安装 npm install -g pm2 常用命令 $ npm i ...

  6. JAVA_SE基础——23.类的定义

    黑马程序员入学blog ... java 面向对象的语言 对象:真实存在的唯一的实物. 比如:我家的狗, 类: 实际就是对某种类型事物的共性属性与行为的抽取.  抽象的概念...   比如说:车   ...

  7. Ansible自动化运维工具-上

    [Ansible特点] 1)Ansible与saltstack均是基于Python语言开发的 2)安装使用简单,基于不同插件和模块实现各种软件,平台,版本的管理以及支持虚拟容器多层级的部署 3)不需要 ...

  8. SpringCloud的注解:汇总篇

    使用注解之前要开启自动扫描功能,如下配置中base-package为需要扫描的包(含子包): 1 <context:component-scan base-package="cn.te ...

  9. 服务器批量管理软件ansible安装以及配置

    1.yum安装(管理主机以及被管理主机都需要安装) yum install epel-release yum install ansible 2.配置管理主机 vim /etc/ansible/hos ...

  10. 0307-关于html

    html最主要的三点: 1.标签的写法.用法 <标签名 属性名1="属性值1" 属性名2="属性值2">内容</标签名> 比如:< ...