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. python控制流 If-else

        控制流 If-else 我们处理现实生活中的问题时会做出决定,就像决定买哪种相机或者怎样更好的打篮球.同样我们写计算机程序的时候也要做相同的事情.我们通过 if-else 语句来做决定,我们使 ...

  2. oc中protocol、category和继承的区别

    OC中protocol.category和继承的区别以前还是有点迷糊,面试的时候说的有点混乱,现在结合一些资料总结一下. 利用继承,多态是一个很好的保持"对扩展开放.对更改封闭"( ...

  3. PHP、Java、Python、C、C++ 这几种编程语言都各有什么特点或优点

    PHP.Java.Python.C.C++ 这几种编程语言都各有什么特点或优点 汇编: C: Java: C#: PHP: Python: Go: Haskell: Lisp: C++: &l ...

  4. 【iOS】swift 排序Sort函数用法(包含NSDictionary排序)

    用了几分钟做的简单翻译 一个例子 直接贴代码,不过多解释 //这是我们的model class imageFile { var fileName = String() var fileID = Int ...

  5. bzoj千题计划242:bzoj4034: [HAOI2015]树上操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=4034 dfs序,树链剖分 #include<cstdio> #include<io ...

  6. vue 在methods中调用mounted中的方法?

    首先可以在data中先声明一个变量 比如 isShow=' ' mounted 中 ---> methods 中 --->  this.sureDelBox(item) 直接this调用 ...

  7. Centos6.7的在虚拟机virulBox下的lamp平台的搭建

    实验环境: linux:小甲鱼带你学C语言,带你飞的提供的体积比较小的centos6.7和virtualBox mysql,apahce,php是燕十八在Linux基础进阶中提供的安装方式: 结果,安 ...

  8. Jenkins 安装、配置与项目新建及构建

    1.Jenkins的安装与配置 1.1 java环境配置 Jenkins基于Java, Linux下安装java只要配置java环境变量即可. 首先,解压java到相应目录,我一般习惯把安装的软件放到 ...

  9. python/SQLAchemy

    python/SQLAchemy SQLAlchemy是Python编程语言下的一款ORM框架,该框架建立在数据库API之上,使用关系对象映射进行数据库操作,简言之便是:将对象转换成SQL,然后使用数 ...

  10. UVA-10714 Ants---蚂蚁模拟

    题目链接: https://vjudge.net/problem/UVA-10714 题目大意: 给你一个长为L厘米的木棍在上面有n只蚂蚁,蚂蚁的爬行时间均为1厘米/秒,两只蚂蚁先遇会立即调转方向,调 ...