spoj+B

题目链接:COT - Count on a tree

题解:跟数组求第K大差不多,这个要求下求下lca,然后区间查询的应该是sum[u]+sum[v]-sum[lca(u,v)]-sum[f[lac(u,v)][0]];

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
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5 1
2 5 2
2 5 3
2 5 4
7 8 2 
Output:
2
8
9
105
#include<bits/stdc++.h>
#include<set>
#include<cstdio>
#include<iomanip>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#define pb push_back
#define ll long long
#define PI 3.14159265
//#define ls l,m,rt<<1
//#define rs m+1,r,rt<<1|1
#define eps 1e-7
typedef unsigned long long ull;
const int mod=1e9+9;
const ll inf=0x3f3f3f3f3f3f3f;
const int maxn=1e5+5;
using namespace std;
int a[maxn],b[maxn],head[maxn],sum[maxn*30],rt[maxn],dep[maxn],f[maxn][20],n,m,tol,sz;
int ls[maxn*30],rs[maxn*30],tot;
struct edge
{
    int to,next;
}eg[maxn*4];
void add_edge(int u,int v)
{
    eg[tol].to=v;
    eg[tol].next=head[u];
    head[u]=tol++;
}
void dfs(int v,int d,int p)
{
    f[v][0]=p;
    dep[v]=d;
    for(int i=head[v];i!=-1;i=eg[i].next)
    {
        if(eg[i].to!=p)dfs(eg[i].to,d+1,v);
    }
}
void init(int c)
{
    dfs(1,0,0);
    for(int k=0;k<19;k++)
    {
        for(int i=1;i<=c;i++)
        {
            if(f[i][k]==0)f[i][k+1]=0;
            else f[i][k+1]=f[f[i][k]][k];
        }
    }
}
void update(int &o,int pre,int l,int r,int x)
{

    o=++tot;
    ls[o]=ls[pre];
    rs[o]=rs[pre];
    sum[o]=sum[pre]+1;
    int m=(l+r)>>1;
    if(l==r)return ;
    if(x<=m)update(ls[o],ls[pre],l,m,x);
    else update(rs[o],rs[pre],m+1,r,x);
}
void dfs1(int v,int p)
{
    update(rt[v],rt[p],1,sz,a[v]);
    for(int i=head[v];i!=-1;i=eg[i].next)
    {
        if(eg[i].to!=p)dfs1(eg[i].to,v);
    }
}
int lca(int u,int v)
{
    if(dep[u]>dep[v])swap(u,v);
    for(int i=0;i<20;i++)
    {
        if(dep[v]-dep[u]>>i&1)v=f[v][i];
    }
    if(v==u)return v;
    for(int i=19;i>=0;i--)
    {
        if(f[v][i]!=f[u][i])
        {
            u=f[u][i];
            v=f[v][i];
        }
    }
    return f[v][0];
}
void build(int &o,int l,int r)
{
    o=++tot;
    sum[o]=0;
    if(l==r)return;
    int m=(l+r)>>1;
    build(ls[o],l,m);
    build(rs[o],m+1,r);
}
int query(int l,int r,int k,int pu,int pv,int pl,int pfl)
{
    if(l==r)return l;
    int m=(l+r)>>1;
    int cnt=sum[ls[pu]]+sum[ls[pv]]-sum[ls[pl]]-sum[ls[pfl]];
    if(cnt>=k)return query(l,m,k,ls[pu],ls[pv],ls[pl],ls[pfl]);
    else return query(m+1,r,k-cnt,rs[pu],rs[pv],rs[pl],rs[pfl]);
}
int main()
{
    while(~scanf("%d %d",&n,&m))
    {
        memset(head,-1,sizeof(head));tot=0;tol=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);b[i]=a[i];
        }
        sort(b+1,b+n+1);
         sz=unique(b+1,b+1+n)-b-1;
        for(int i=1;i<=n;i++)
        {
             a[i]=lower_bound(b+1,b+1+sz,a[i])-b;
        }
        for(int i=0;i<n-1;i++)
        {
            int u,v;
            scanf("%d %d",&u,&v);
            add_edge(u,v);
            add_edge(v,u);
        }
        init(n);
        build(rt[0],1,sz);
        dfs1(1,0);
        while(m--)
        {
            int u,v,k;
            scanf("%d %d %d",&u,&v,&k);
            int lc=lca(v,u);
          //  cout<<lc<<"*"<<endl;
            int id=query(1,sz,k,rt[u],rt[v],rt[lc],rt[f[lc][0]]);
            printf("%d
",b[id]);
        }
    }
    return 0;
}
 
原文地址:https://www.cnblogs.com/lhclqslove/p/8679080.html