SPOJ COT - Count on a tree树链剖分加主席树
来源:互联网 发布:种植牙费用 知乎 编辑:程序博客网 时间:2024/06/02 19:43
Description
You are given a tree with N nodes.The tree nodes are numbered from1 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 nodeu 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 nodeu to node v.
Output
For each operation,print its result.
Example
Input:8 58 5105 2 9 3 8 5 7 71 2 1 31 43 53 63 74 82 5 12 5 22 5 32 5 47 8 2
Output:2891057
题目大意:给你一颗树,m次询问,问节点u到v第k大的数是多少。
思路:若是求一个数组的L到R的第k大的话,直接一个主席树就可以搞定了,现在变成了树上,然后其实是直接树剖,把u到v分成最多logn段的连续序列,对每个序列求出T[r] - T[l-1]然后相加起来,就是这logn段的左区间和,做法跟求数组的第k大一样。还有就是建主席树的时候放到树剖节点映射线段树那一部分,因为要保证重链上的节点是连续的。
#include <cstdio>#include <cstring>#include <queue>#include <cmath>#include <algorithm>#include <iostream>#include <cstdlib>using namespace std;//typedef __int64 LL;const int maxn = 100005;int w[maxn],fa[maxn],dep[maxn],num[maxn],son[maxn],top[maxn],vis[maxn],head[maxn],cnt,cou;int T[maxn],lson[maxn*50],rson[maxn*50],c[maxn*50],tot,len,b[maxn],tt,user[maxn],usel[maxn];int n,m;struct Edge{ int v,next;}e[maxn*2];void add(int a,int b){ e[cnt].v = b; e[cnt].next = head[a]; head[a] = cnt++;}void init(){ cou = cnt = tot = len = 0; tt = 1; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son));}void hase(int k){ sort(b,b+k); len = unique(b,b+k) - b;}int get_hase(int now){ return (lower_bound(b,b+len,now) - b);}int build(int l,int r){ int root = tot++; c[root] = 0; if(l != r) { int mid = (l + r) >> 1; lson[root] = build(l,mid); rson[root] = build(mid+1,r); } return root;}void dfs1(int u,int v,int deep){ fa[v] = u; num[v] = 1; dep[v] = deep; int i; for(i = head[v]; i != -1; i = e[i].next) { int end = e[i].v; if(end == u) continue; dfs1(v,end,deep+1); num[v] += num[end]; if(son[v] == -1 || num[son[v]] < num[end]) { son[v] = end; } }}int insert1(int root,int pos,int val){ int newroot = tot++; c[newroot] = c[root] + val; int tmp = newroot; int l = 0,r = len - 1; while(l < r) { int mid = (l + r) >> 1; if(pos <= mid) { lson[newroot] = tot++; rson[newroot] = rson[root]; root = lson[root]; newroot = lson[newroot]; r = mid; } else { lson[newroot] = lson[root]; rson[newroot] = tot++; root = rson[root]; newroot = rson[newroot]; l = mid + 1; } c[newroot] = c[root] + val; } return tmp;}void dfs2(int u,int v){ top[v] = u; T[tt] = insert1(T[tt-1],get_hase(w[v]),1); tt++; vis[v] = ++cou; if(son[v] != -1) { dfs2(u,son[v]); } else return; int i; for(i = head[v]; i != -1; i = e[i].next) { int end = e[i].v; if(end == son[v] || end == fa[v]) continue; dfs2(end,end); }}void solve(int a,int b1,int pos){ int q = top[a],w = top[b1]; int t = 0; while(q != w) { if(dep[q] < dep[w]) { swap(q,w); swap(a,b1); } user[t] = T[vis[a]],usel[t] = T[vis[q]-1]; t++; a = fa[q]; q = top[a]; } if(dep[a] > dep[b1]) swap(a,b1); user[t] = T[vis[b1]],usel[t] = T[vis[a]-1]; t++; int l = 0,r = len - 1; int rootr,rootl,i; while(l < r) { int sum = 0; int mid = (l + r) >> 1; for(i = 0; i < t; i++) { sum += c[lson[user[i]]] - c[lson[usel[i]]]; } if(sum < pos) { pos -= sum; l = mid + 1; for(i = 0; i < t; i++) { user[i] = rson[user[i]]; usel[i] = rson[usel[i]]; } } else { r = mid; for(i = 0; i < t; i++) { user[i] = lson[user[i]]; usel[i] = lson[usel[i]]; } } } printf("%d\n",b[l]);}int main(){ while(scanf("%d %d",&n,&m) != EOF) { int i; init(); for(i = 1; i <= n; i++) { scanf("%d",&w[i]); b[len++] = w[i]; } hase(len); int q,w; for(i = 1; i < n; i++) { scanf("%d %d",&q,&w); add(q,w); add(w,q); } T[0] = build(0,len-1); dfs1(1,1,1); dfs2(1,1); while(m--) { int A,B,C; scanf("%d %d %d",&A,&B,&C); solve(A,B,C); } } return 0;}
- SPOJ COT - Count on a tree树链剖分加主席树
- 【SPOJ-COT】Count on a tree【主席树】【LCA】
- [BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- [省选前题目整理][BZOJ 2588][SPOJ COT]Count On a Tree(DFS序主席树)
- SPOJ COT Count on a tree (树上k大 主席树模板)
- spoj cot Count on a tree
- SPOJ COT 10628 Count on a tree
- SPOJ-COT-Count on a tree
- SPOJ COT Count on a tree
- 【主席树】 SPOJ Count on a tree
- spoj Count on a tree【主席树】
- SPOJ COT Count on a tree 树上第k小
- spoj 10628 Count on a tree (主席树+lca)
- SPOJ 10628 Count on a tree (lca+主席树)
- 2588: Spoj 10628. Count on a tree 主席树+LCA
- spoj Count on a tree【主席树+在线LCA】
- BZOJ 2588: Spoj 10628. Count on a tree|主席树
- 【bzoj2588】Spoj 10628. Count on a tree LCA+主席树
- StringUtils工具类用法
- Android命令
- opencv学习(一)书本《学习Opencv》(中文版)的第二章的10个入门样例的分析
- poj 1797 Heavy transportation 最短路
- Java File类学习笔记4:自定义一个类,过滤指定扩展名的文件
- SPOJ COT - Count on a tree树链剖分加主席树
- spring mvc controller取到的中文参数是乱码
- Java:按值传递还是按引用传递详细解说
- iOS button 同时设定图片和文字
- Makefile经典教程(掌握这些足够)
- qt 编程 hello-world
- Linux基础学习-01
- 图像处理那张熟悉的面孔——Lena
- SenchaTouchq