【BZOJ2588】Count On a Tree(主席树)

【BZOJ2588】Count On a Tree(主席树)

题面

题目描述

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

输入格式:

第一行两个整数N,M。

第二行有N个整数,其中第i个整数表示点i的权值。

后面N-1行每行两个整数(x,y),表示点x到点y有一条边。

最后M行每行两个整数(u,v,k),表示一组询问。

输出格式:

M行,表示每个询问的答案。

输入输出样例

输入样例#1:

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
0 5 2
10 5 3
11 5 4
110 8 2

输出样例#1:

2
8
9
105
7

说明

HINT:

N,M<=100000

题解

链上的第k大->主席树
这题怎么搞得话
对于每一个节点建立一个线段树(显然开不下)
每个节点继承父节点再加上自己
主席树搞一下
查询的时候,跳\(u,v,lca,father(lca)\)四棵线段树就行了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define MAX 110000
#define lson (t[now].ls)
#define rson (t[now].rs)
inline int read()
{
    int x=0,t=1;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
struct Line
{
    int v,next;
}e[MAX<<1];
int h[MAX],cnt=1;
int n,m,sum;
int a[MAX],S[MAX],tot,z[MAX];
int rt[MAX];
struct Node
{
    int ls,rs;
    int v;
}t[MAX<<5];
inline void Add(int u,int v)
{
    e[cnt]=(Line){v,h[u]};
    h[u]=cnt++;
}
void Build(int &now,int l,int r)
{
    now=++tot;
    if(l==r)return;
    int mid=(l+r)>>1;
    Build(lson,l,mid);
    Build(rson,mid+1,r);
}
void Update(int &now,int ff,int l,int r,int pos)
{
    now=++tot;
    t[now]=t[ff];
    t[now].v++;
    if(l==r)return;
    int mid=(l+r)>>1;
    if(pos<=mid)Update(lson,t[ff].ls,l,mid,pos);
    else Update(rson,t[ff].rs,mid+1,r,pos);
}
int Query(int r1,int r2,int r3,int r4,int l,int r,int k)
{
    if(l==r)return l;
    int tmp=t[t[r1].ls].v+t[t[r2].ls].v-t[t[r3].ls].v-t[t[r4].ls].v;
    int mid=(l+r)>>1;
    if(k<=tmp)return Query(t[r1].ls,t[r2].ls,t[r3].ls,t[r4].ls,l,mid,k);
    else return Query(t[r1].rs,t[r2].rs,t[r3].rs,t[r4].rs,mid+1,r,k-tmp);
}
int hson[MAX],fa[MAX],size[MAX],dep[MAX],top[MAX];
void dfs1(int u,int ff)
{
    fa[u]=ff;size[u]=1;dep[u]=dep[ff]+1;
    Update(rt[u],rt[ff],1,sum,a[u]);
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if(v==ff)continue;
        dfs1(v,u);
        size[u]+=size[v];
        if(size[v]>size[hson[u]])hson[u]=v;
    }
}
void dfs2(int u,int tp)
{
    top[u]=tp;
    if(hson[u])dfs2(hson[u],tp);
    for(int i=h[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if(v==fa[u]||v==hson[u])continue;
        dfs2(v,v);
    }
}
int LCA(int u,int v)
{
    while(top[u]!=top[v])
    {
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        u=fa[top[u]];
    }
    return dep[u]<dep[v]?u:v;
}
int main()
{
    n=sum=read();m=read();
    for(int i=1;i<=n;++i)S[i]=a[i]=z[i]=read();
    sort(&S[1],&S[n+1]);
    sum=unique(&S[1],&S[sum+1])-S-1;
    for(int i=1;i<=n;++i)a[i]=(lower_bound(&S[1],&S[sum+1],a[i])-S);
    for(int i=1;i<n;++i)
    {
        int x=read(),y=read();
        Add(x,y);Add(y,x);
    }
    Build(rt[0],1,sum);
    dfs1(1,0);dfs2(1,1);
    int lans=0;
    while(m--)
    {
        int u=read()^lans,v=read(),k=read();
        int lca=LCA(u,v);
        printf("%d\n",lans=S[Query(rt[u],rt[v],rt[lca],rt[fa[lca]],1,sum,k)]);
    }
    return 0;
}

posted @ 2017-12-25 19:21  小蒟蒻yyb  阅读(323)  评论(0编辑  收藏  举报