SPOJ

来源:互联网 发布:工艺软件有什么 编辑:程序博客网 时间:2024/06/05 17:10

Count on a tree

 SPOJ - COT 

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 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 
题意:给出一颗树,求两结点第k小的数
分析:跟求区间第K大差不多,这次是维护一个树上的信息。
 那么结果为 tree[a]+tree[b]-tree[lca(a,b)]-tree[father[lca(a,b)]] 因为lca结点需要保留,所以是减去父亲结点(这里的father是父亲不是祖先)
AC代码:
#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<math.h>using namespace std;const int maxn=100500;struct zxtree{int num,lson,rson;}tree[maxn<<5];struct edge{int u,v;edge(){}edge(int uu,int vv){u=uu,v=vv;}};vector<edge>G;vector<int>v[maxn];int root[maxn];int val[maxn],hash1[maxn];int cnt;int father[maxn][40],fa[maxn],maxdeep,deep[maxn];void addedge(int a,int b){G.push_back(edge(a,b));G.push_back(edge(b,a));int m=G.size();v[a].push_back(m-2);v[b].push_back(m-1);}void bulidzxtree(int &v,int l,int r){v=++cnt;tree[v].num=0;if(l==r) return;int mid=(l+r)>>1;bulidzxtree(tree[v].lson,l,mid);bulidzxtree(tree[v].rson,mid+1,r);}int Binary_search(int *p,int x,int r){int l=1;while(l<=r){int mid=(l+r)>>1;if(p[mid]<x)l=mid+1;elser=mid-1;}return l;}void init(int n){memset(root,0,sizeof(root));memset(father,0,sizeof(father));memset(fa,0,sizeof(fa));memset(deep,0,sizeof(deep));maxdeep=log(n*1.0)/log(2.0);for(int i=0;i<=n;i++)v[i].clear();G.clear();}void update(int p,int &v,int l,int r,int x){v=++cnt;tree[v]=tree[p];tree[v].num++;if(l==r) return;int mid=(l+r)>>1;if(x>mid)update(tree[p].rson,tree[v].rson,mid+1,r,x);elseupdate(tree[p].lson,tree[v].lson,l,mid,x);}void dfs(int rt,int t){update(root[fa[rt]],root[rt],1,t,val[rt]);for(int i=1;i<=maxdeep;i++){father[rt][i]=father[father[rt][i-1]][i-1];if(father[rt][i]==0)break;}for(int i=0;i<v[rt].size();i++){edge &e=G[v[rt][i]];if(father[rt][0]!=e.v){father[e.v][0]=rt;fa[e.v]=rt;deep[e.v]=deep[rt]+1;dfs(e.v,t);}}}int lca(int a,int b){if(deep[a]>deep[b])swap(a,b);for(int i=maxdeep;i>=0;i--){if(deep[a]<deep[b]&&deep[a]<=deep[father[b][i]]){b=father[b][i];}}if(a==b)return a;for(int i=maxdeep;i>=0;i--){if(father[a][i]!=father[b][i]){a=father[a][i];b=father[b][i];}}if(a!=b)a=father[a][0];return a;}int query(int a,int b,int lc,int ff,int l,int r,int k){if(l==r) return l;int mid=(l+r)>>1;int ans=tree[tree[a].lson].num+tree[tree[b].lson].num-tree[tree[lc].lson].num-tree[tree[ff].lson].num;//printf("! %d\n",ans);if(k<=ans)query(tree[a].lson,tree[b].lson,tree[lc].lson,tree[ff].lson,l,mid,k);elsequery(tree[a].rson,tree[b].rson,tree[lc].rson,tree[ff].rson,mid+1,r,k-ans);}int main(){int n,m;while(scanf("%d%d",&n,&m)==2){init(n);cnt=0;for(int i=1;i<=n;i++){scanf("%d",&val[i]);hash1[i]=val[i];}sort(hash1+1,hash1+n+1);int t=unique(hash1+1,hash1+1+n)-hash1-1;for(int i=1;i<=n;i++){val[i]=Binary_search(hash1,val[i],t);//val[i]=lower_bound(hash+1,hash+t+1,val[i])-hash;}bulidzxtree(root[0],1,t);int rt;for(int i=0;i<n-1;i++){int a,b;scanf("%d%d",&a,&b);father[b][0]=a;addedge(a,b);if(!father[a][0])rt=a;}deep[rt]=1;dfs(rt,t);for(int i=0;i<m;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);int lc=lca(a,b);int s=query(root[a],root[b],root[lc],root[fa[lc]],1,t,c);printf("%d\n",hash1[s]);}}}