【可持久化线段树】[SPOJ COT]Count on a tree
2015-11-27 13:47
465 查看
题目大意:给定一棵树,然后询问连个节点间路径上的权值的第K小的权值大小
题目分析:和普通的第K大的可持久化线段树差距不大,但是要写个LCA可以发现Tree(a)+Tree(b)−Tree(LCA)−LCA(fa[LCA])Tree(a)+Tree(b)-Tree(LCA)-LCA(fa[LCA])就是两个节点之间的线段树了,然后按照普通的可持久化线段树搞一搞就好了
题目分析:和普通的第K大的可持久化线段树差距不大,但是要写个LCA可以发现Tree(a)+Tree(b)−Tree(LCA)−LCA(fa[LCA])Tree(a)+Tree(b)-Tree(LCA)-LCA(fa[LCA])就是两个节点之间的线段树了,然后按照普通的可持久化线段树搞一搞就好了
[code]#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 1e5+100; struct node{ int ch[2]; int sum; }pool[MAXN*21]; int roots[MAXN+10], q[MAXN+10], p[MAXN+10], tot, nlen; struct Ed{ int u, v; Ed *next; }Edges[MAXN*2+10], *ecnt=Edges, *adj[MAXN+10]; int Fa[MAXN+10][20], Dep[MAXN+10]; void addedge(int u, int v){ ++ecnt; ecnt->v = v; ecnt->next = adj[u]; adj[u] = ecnt; } void Insert(int &u, int l, int r, int v){ ++tot; pool[tot] = pool[u]; u = tot; pool[u].sum ++; if(l == r) return ; int mid = (l + r) >> 1; if(v <= mid) Insert(pool[u].ch[0], l, mid, v); else Insert(pool[u].ch[1], mid+1, r, v); } void dfs(int u, int fa){ Fa[u][0] = fa; for(int i=0;i<18;i++) Fa[u][i+1] = Fa[Fa[u][i]][i]; Dep[u] = Dep[fa] + 1; roots[u] = roots[fa]; Insert(roots[u], 1, nlen, q[u]); for(Ed *p=adj[u];p;p=p->next){ if(p->v == fa) continue; dfs(p->v, u); } } int LCA(int a, int b){ if(Dep[a] > Dep[b]) swap(a, b); for(int k=18;k>=0;k--) if(Dep[a] <= Dep[Fa[b][k]]) b = Fa[b][k]; if(a == b) return a; for(int k=18;k>=0;k--){ if(Fa[a][k] != Fa[b][k] && Fa[a][k] != -1){ a = Fa[a][k]; b = Fa[b][k]; } } return Fa[a][0]; } int Query(int lroot, int rroot, int lcroot, int lcfroot, int l, int r, int k){ if(l >= r) return l; int mid = (l + r) >> 1; int cz = pool[pool[lroot].ch[0]].sum; cz += pool[pool[rroot].ch[0]].sum; cz -= pool[pool[lcroot].ch[0]].sum; cz -= pool[pool[lcfroot].ch[0]].sum; if(k <= cz) return Query(pool[lroot].ch[0], pool[rroot].ch[0], pool[lcroot].ch[0], pool[lcfroot].ch[0], l, mid, k); return Query(pool[lroot].ch[1], pool[rroot].ch[1], pool[lcroot].ch[1], pool[lcfroot].ch[1], mid+1, r, k-cz); } int main(){ memset(Fa,-1, sizeof Fa); int n, m, a, b, k; scanf("%d%d", &n, &m); for(int i=1;i<=n;i++){ scanf("%d", &q[i]); p[i] = q[i]; } sort(p+1, p+1+n); nlen = unique(p+1, p+1+n) - (p+1); for(int i=1;i<=n;i++) q[i] = lower_bound(p+1, p+1+nlen, q[i]) - p; for(int i=2;i<=n;i++){ scanf("%d%d", &a, &b); addedge(a, b); addedge(b, a); } dfs(1, 0); for(int i=1;i<=m;i++){ scanf("%d%d%d", &a, &b, &k); int lc = LCA(a, b); printf("%d\n", p[Query(roots[a], roots[b], roots[lc], roots[Fa[lc][0]], 1, nlen, k)]); } return 0; } /* 2 1 1 2 1 2 1 2 2 */
相关文章推荐
- 测透51汇编 51单片机所有程序(51学习的纪念)
- 动态姿态平衡分析
- OMPL138及U-Boot的启动过程分析(二)
- 木马藏身于系统进程中
- android应用性能测试之CPU和内存占用
- JVM详解链接地址
- 【Protobuf】
- mybatis 使用动态SQL
- Android toolbar添加SearchView混淆打包成功后访问出错
- js原型的理解之一切皆对象
- CSS定位
- [Android]打开eclipse报错:发现了以元素 'd:skin' 开头的无效内容。此处不应含有子元素。
- hadoop常见错误整理
- centos配置jdk
- 微信自定义推送模版消息
- JAVA多线程实现的三种方式
- 市航天纪念钞 出门就升值
- 1041. Be Unique (20)
- ARM架构下linux设备树加载的方法
- ViewAnimator及其子类