BZOJ2588 - Spoj 10628. Count on a tree

BZOJ2588 - Click Here

  

Description

  给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

  

Input

  第一行两个整数N,M。(N,M<=100000)

  第二行有N个整数,其中第i个整数表示点i的权值。

  后面N-1行每行两个整数(x,y),表示点x到点y有一条边。

  最后M行每行两个整数(u,v,k),表示一组询问。

  

Output

  M行,表示每个询问的答案。最后一个询问不输出换行符

  

Solutions

  树上u->v路径中的第k大,其实等价于u->lca(u,v)和v->lca(u,v)这两条路径合成的数列中的第k大。因此,每个(u,v)询问都可以拆分成树上的两条链。那么,就可以利用DFS序树上构建主席树。在主席树上时,利用子树的性质进行二分查找,从而寻找到第k大。主席树上的权值表示为tree[u]+tree[v]-tree[lca(u,v)]-tree[fa[lca(u,v)],其中fa[i]表示i节点的父亲。

  值得注意的是,点i的权值题目未给出的,因此最好离散化节点,防止RE。

  

CODE

CODE - Click Here

本站总访问量次 | 本站访客数人次

Powered by Hexo | Designed by iTimeTraveler | Refined by CSHwang