描述

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

分析

  • 想用树链剖分但是发现不知道怎么套主席树.
  • 正解是LCA, 只要维护根节点到每个结点u的权值线段树. 因为主席树求第k大支持减法, 所以最终答案就是线段树 u+v-lca(u,v)-fa[lca(u,v)] 中的第k大.
  • 调了半天发现在用lower_bound查找离散后的权值时, unique后的T数组有序不假但重复元素被挪到了数组尾, 所以不能再用原来的T+n+1作为二分查找的上界了.
#include #include #include using namespace std;
const int maxn = 100000 + 10;
const int maxm = 3000000;
const int DEP = 20;
vectorG[maxn];
int n, m, tot, node_cnt;
int A[maxn], T[maxn];
int dep[maxn], fa[maxn][DEP];
int root[maxm], lc[maxm], rc[maxm], s[maxm];
#define M (L+R>>1)
void modify(int& x, int y, int L, int R, int d) {
x = ++node_cnt;
lc[x] = lc[y]; rc[x] = rc[y]; s[x] = s[y] + 1;
if(L == R) return;
if(d <= M) modify(lc[x], lc[y], L, M, d);
else modify(rc[x], rc[y], M+1, R, d);
}
int query(int u, int v, int x, int y, int L, int R, int k) {
if(L == R) return L;
int ls = s[lc[u]] + s[lc[v]] - s[lc[x]] - s[lc[y]];
if(k <= ls) return query(lc[u], lc[v], lc[x], lc[y], L, M, k);
return query(rc[u], rc[v], rc[x], rc[y], M+1, R, k-ls);
}
void dfs(int u, int x) {
dep[u] = dep[fa[u][0] = x] + 1;
for(int i = 1; i < DEP; i++)
if((1<<= dep[u]) fa[u][i] = fa[fa[u][i-1]][i-1]; else break; modify(root[u], root[x], 1, tot, A[u]); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(v != x) dfs(v, u); } } int lca(int x, int y) { if(dep[x] < dep[y]) swap(x, y); int delta = dep[x]-dep[y]; for(int i = 0; i < DEP; i++) if(delta&(1<= 0; i--) if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; return fa[x][0]; } int main() { int n, m; scanf("%d %d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d", &A[i]); T[i] = A[i]; } sort(T+1, T+n+1); tot = unique(T+1, T+n+1) - T-1; for(int i = 1; i <= n; i++) A[i] = lower_bound(T+1, T+tot+1, A[i]) - T; for(int i = 1; i < n; i++) { int u, v; scanf("%d %d", &u, &v); G[u].push_back(v); G[v].push_back(u); } dfs(1, 0); int ans = 0; for(int i = 1; i <= m; i++) { int u, v, k; scanf("%d %d %d", &u, &v, &k); u ^= ans; int x = lca(u, v), y = fa[x][0]; ans = T[query(root[u], root[v], root[x], root[y], 1, tot, k)]; if(i < m) printf("%d\n", ans); else printf("%d", ans); } return 0; } 

BZOJ-2588-Count-on-a-tree-SPOJ10628-LCA+主席树相关推荐

  1. [BZOJ 2588]Count on a tree

    传送门 LCA+主席树(可持久化线段树) 取一个点为根,每棵线段树记录树上节点到根的链上的权在数轴上的分布(当然要离散化), 则对于两个点u,v的路径上的数在数轴上的分布可以表示为tree[u]+tr ...

  2. BZOJ 2588: Spoj 10628. Count on a tree 树上跑主席树

    2588: Spoj 10628. Count on a tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/J ...

  3. BZOJ2588 Count on a tree 【树上主席树】

    2588: Spoj 10628. Count on a tree Time Limit: 12 Sec  Memory Limit: 128 MB Submit: 7577  Solved: 185 ...

  4. SPOJ - COT Count on a tree(LCA+主席树+离散化)

    题目链接:点击查看 题目大意:给出一棵树,每个点都有一个权值,现在给出m个询问,每次询问的格式是u,v,k,要求输出u-v这条路径上第k大的数 题目分析:一看到第k大的数就会想到主席树,既然是在树上的 ...

  5. 计蒜客 - Distance on the tree(LCA+主席树)

    题目链接:点击查看 题目大意:给出一颗含有n个节点的树,每条边都有权值,现在给出m个询问,每次询问的格式为u,v,w,我们需要求出在路径u-v上,边权小于等于w的边的个数 题目分析:多的不说了,上一个 ...

  6. 【BZOJ1483】【codevs2335】【hdu5997】梦幻布丁+加强版,LCA+主席树

    传送门1 传送门2 传送门3 思路: 这还要从上一周的BC说起-- 因为正好放大周,在家里颓了一天后准备BC#90 干完两个签到题以后开始搞T3 抽象了很久YY出来一个并查集+主席树 连蒙带骗写了一发 ...

  7. BZOJ 2588: Spoj 10628. Count on a tree( LCA + 主席树 )

    Orz..跑得还挺快的#10 自从会树链剖分后LCA就没写过倍增了... 这道题用可持久化线段树..点x的线段树表示ROOT到x的这条路径上的权值线段树 ----------------------- ...

  8. SPOJ - COT Count on a tree [LCA+主席树]【数据结构】

    题目链接:http://www.spoj.com/problems/COT/en/ -------------------------------------- COT - Count on a tr ...

  9. 主席树 || 可持久化线段树 || LCA || BZOJ 2588: Spoj 10628. Count on a tree || Luogu P2633 Count on a tree...

    题面: Count on a tree 题解: 主席树维护每个节点到根节点的权值出现次数,大体和主席树典型做法差不多,对于询问(X,Y),答案要计算ans(X)+ans(Y)-ans(LCA(X,Y) ...

  10. BZOJ 2588 Spoj 10628 Count on a tree | 树上主席树

    BZOJ 2588 Count on a tree 题面 求树上两点之间路径上第k大的点权. 题解 一开始看到这道题觉得是树剖,然后又听说是主席树,然后以为是主席树+树剖,差点没吓死-- 然后发现,如 ...

最新文章

  1. Bitcoin 中的挖矿算法(2) 难度值说明
  2. ftl不存在为真_FreeMarker 处理不存在的变量
  3. 作业27-登录之后更新导航
  4. 【转】杀人后一个孩子的做法…不看你会后悔的…
  5. php中函数参数个数问题
  6. 2017.9.12 连通数 失败总结
  7. 计算机组成输出设备的缩写,信息概念 计算机组成
  8. 开源GIS(十二)——openlayers中加载切片原理
  9. 多线程3,线程池封装库
  10. 数学算法对计算机编程的优化
  11. 语音识别之DTW算法的应用(Python)
  12. CSDN的手机APP可以写博客了
  13. Ms08067实验室 JAVA代码审计实战班:开课喽!!
  14. mac terminal终端快速打开指定文件夹
  15. 爬虫之-bilibili视频下载-下载链接获取
  16. 【华为机试真题 Python实现】机器人走迷宫
  17. 阿里云安全组设定(虚拟机端口打开)
  18. Android面试题之动画+事件处理篇
  19. java走迷宫_走迷宫问题Java递归
  20. hadoop实战(三) 使用HDFS操作文件

热门文章

  1. [云炬创业基础笔记]创业计划书常见问题
  2. 科大星云诗社动态20210526
  3. 解决Sublime Text打开C++文件出现中文乱码
  4. 吴恩达《卷积神经网络》精炼笔记(3)-- 目标检测
  5. oracle 如何形成死锁,ORACLE死锁
  6. python读取redis存储数据的存储时间_Python读写Redis数据库操作示例
  7. C#中线程池的简单应用
  8. C++ 类的静态成员(static)
  9. docker 必然用到的一些指令
  10. Class.forName有什么作用