spoj cot: Count on a tree 主席树

10628. Count on a tree

Problem code: 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 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
7

NOI前的最后一道题编这道主席树的题算是了解了对于主席树的“恐惧“。
这道题的大致思路是对于树上每一个点,都在其父节点基础上建主席树。
第一次编没有初始化建树操作的线段树来优化内存。还算比较顺利。以后看题的时候注意对于没有指明范围的量离散化。
虽然参加不了NOI现场赛,但还是希望自己在同步赛中rp++
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 211000
#define MAXE 211000
#define MAXT 16001000
int n,m;
int ptr[MAXN];
struct Edge
{
        int np;
        Edge *next;
}E[MAXE],*V[MAXN];
int tope=-1;
void addedge(int x,int y)
{
        E[++tope].np=y;
        E[tope].next=V[x];
        V[x]=&E[tope];
}
int wei[MAXN];
int depth[MAXN];
int fa[MAXN];
void dfs(int now,int d)
{
        Edge *ne;
        depth[now]=d;
        for (ne=V[now];ne;ne=ne->next)
        {
                if (ne->np==fa[now])continue;
                fa[ne->np]=now;
                dfs(ne->np,d+1);
        }
}
int jump[MAXN][20];
void init_lca()
{
        int i,j;
        for (i=1;i<=n;i++)
        {
                jump[i][0]=fa[i];
        }
        for (j=1;j<20;j++)
        {
                for (i=1;i<=n;i++)
                {
                        jump[i][j]=jump[jump[i][j-1]][j-1];
                }
        }
}
void swim(int &now,int d)
{
        int i=0;
        while (d)
        {
                if (d&1)now=jump[now][i];
                i++;
                d>>=1;
        }
}
int lca(int x,int y)
{
        if (depth[x]<depth[y])
        {
                swim(y,depth[y]-depth[x]);
        }
        if (depth[y]<depth[x])
        {
                swim(x,depth[x]-depth[y]);
        }
        if (x==y)return x;
        int i;
        for (i=19;i>=0;i--)
        {
                if (jump[x][i]!=jump[y][i])
                {
                        x=jump[x][i];
                        y=jump[y][i];
                }
        }
        return fa[x];
}
struct node
{
        int lch,rch,sum;
}tree[MAXT];
int topt=0;
int get_node(node *nd)
{
        if (nd==NULL)
        {
                return ++topt;
        }
        topt++;
        tree[topt]=*nd;
        return topt;
}
/*void build_tree(int &now,int l,int r)
{
        now=++topt;
//        tree[now].l=l;
//        tree[now].r=r;
        if (l==r)return ;
        int mid=(l+r)/2;
        build_tree(tree[now].lch,l,mid);
        build_tree(tree[now].rch,mid+1,r);
}*/
void add_val(int &now,int &base,int l,int r,int pos,int v)
{
        now=get_node(&tree[base]);
        tree[now].sum+=v;
        if (l==pos&&r==pos)
        {
                return ;
        }
        int mid=(l+r)/2;
        if (pos<=mid)
        {
                add_val(tree[now].lch,tree[base].lch,l,mid,pos,v);
                return ;
        }
        if (mid<pos)
        {
                add_val(tree[now].rch,tree[base].rch,mid+1,r,pos,v);
                return ;
        }
}
int root[MAXN];
void dfs2(int now)
{
        Edge *ne;
        add_val(root[now],root[fa[now]],1,m,wei[now],1);
        for (ne=V[now];ne;ne=ne->next)
        {
                if (ne->np==fa[now])continue;
                dfs2(ne->np);
        }
}
struct weight_t
{
        int id,w;
}wei2[MAXN];
bool cmp_w(const weight_t &w1,const weight_t &w2)
{
        return w1.w<w2.w;
}
bool cmp_id(const weight_t &w1,const weight_t &w2)
{
        return w1.id<w2.id;
}
int main()
{
        //freopen("input.txt","r",stdin);
        int i,j,k,x,y,z;
        int q;
        m=100010;
        scanf("%d%d",&n,&q);
        for (i=1;i<=n;i++)
        {
                scanf("%d",&wei2[i].w);
                wei2[i].id=i;
        }
        sort(&wei2[1],&wei2[n+1],cmp_w);
        x=0;y=-1;
        for (i=1;i<=n;i++)
        {
                if (wei2[i].w!=y)
                {
                        y=wei2[i].w;
                        ptr[x+1]=wei2[i].w;
                        wei2[i].w=++x;
                }else wei2[i].w=x;
        }
        sort(&wei2[1],&wei2[n+1],cmp_id);
        for (i=1;i<=n;i++)
                wei[i]=wei2[i].w;
        for (i=0;i<n-1;i++)
        {
                scanf("%d%d",&x,&y);
                addedge(x,y);
                addedge(y,x);
        }
        Edge *ne;
        dfs(1,0);
        init_lca();
        //build_tree(root[0],1,m);
        add_val(root[1],root[0],1,m,wei[1],1);
        for (ne=V[1];ne;ne=ne->next)
                dfs2(ne->np);
        int t,temp;
        int a[5],topa;
        int ans;
        int l,r,mid;
        for (i=0;i<q;i++)
        {
                scanf("%d%d%d",&x,&y,&z);
                t=lca(x,y);
                if (t!=1)a[0]=root[fa[t]];
                else a[0]=0;
                a[1]=root[t];
                a[2]=root[x];
                a[3]=root[y];
                ans=0;
                l=1,r=m;
                while (true)
                {
                        mid=(l+r)/2;
                        temp=ans;
                        if (l==r)break;
                        if (a[0])ans-=tree[tree[a[0]].lch].sum;
                        if (a[1])ans-=tree[tree[a[1]].lch].sum;
                        if (a[2])ans+=tree[tree[a[2]].lch].sum;
                        if (a[3])ans+=tree[tree[a[3]].lch].sum;
                        if (ans>=z)
                        {
                                if (a[0])a[0]=tree[a[0]].lch;
                                if (a[1])a[1]=tree[a[1]].lch;
                                if (a[2])a[2]=tree[a[2]].lch;
                                if (a[3])a[3]=tree[a[3]].lch;
                                r=mid;
                                ans=temp;
                        }else
                        {
                                if (a[0])a[0]=tree[a[0]].rch;
                                if (a[1])a[1]=tree[a[1]].rch;
                                if (a[2])a[2]=tree[a[2]].rch;
                                if (a[3])a[3]=tree[a[3]].rch;
                                l=mid+1;
                        }
                }    
                printf("%d
",ptr[l]);
        }
}
by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

本博客已停用,新博客地址:http://mhy12345.xyz

原文地址:https://www.cnblogs.com/mhy12345/p/3870648.html