码迷,mamicode.com
首页 > 其他好文 > 详细

SCUT106 花式AC 主席树版本

时间:2019-08-10 21:58:03      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:版本   bsp   代码   upd   ini   ret   bit   sort   int()   

网址:https://scut.online/p/106

题意:

给出一个点权树以$1$为根节点,求子树有几个节点的权值小于等于$k$。

题解:

主席树版本,先对树$dfs$求出第一次进入某节点的时间戳,然后同时处理出子树的节点数,然后求出的$dfs$序中某节点的时间戳后长度为该节点的子树的大小$-1$就是这个节点的子树对应的序列,在主席树上求个数即可。原理类似于求区间第k大,只不过是每棵主席树都保存了序列前$m(1 \leq m \leq n)$个数大小是$[1,n]$数的总个数,然后查询时查询区间中的$[1,k]$的数的个数即可。由于本题数值过大,因为权值是离散化的,所以输入的$k$也要离散化,找到小于等于k的第一个数。

AC代码:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=100005;
struct cheiftree
{
    struct node
    {
        int l,r,sum;
    };
    node tr[MAXN*20];
    int rt[MAXN];
    int cnt=0;
    void init()
    {
        cnt=0;
    }
    void build(int &rt,int l,int r)
    {
        rt=++cnt;
        tr[rt].sum=0;
        int m=(l+r)/2;
        if(l==r)
            return;
        build(tr[rt].l,l,m);
        build(tr[rt].r,m+1,r);
    }
    void update(int &rt,int l,int r,int k)
    {
        tr[++cnt]=tr[rt];
        rt=cnt;
        ++tr[rt].sum;
        if(l==r)
            return;
        int m=(l+r)/2;
        if(k<=m)
            update(tr[rt].l,l,m,k);
        else  
            update(tr[rt].r,m+1,r,k);
    }
    int query(int rl,int rr,int l,int r,int val)
    {
        if(l==r)
            return tr[rr].sum-tr[rl].sum;
        int m=(l+r)/2;
        if(val<=m)
            return query(tr[rl].l,tr[rr].l,l,m,val);
        else if(val>m)
            return tr[tr[rr].l].sum-tr[tr[rl].l].sum+query(tr[rl].r,tr[rr].r,m+1,r,val);
    }
};
cheiftree tr;
int in[MAXN],a[MAXN],b[MAXN],size[MAXN],vis[MAXN];
int cnt=0;
vector<int>E[MAXN];
void print()
{
    for(int i=1;i<=tr.cnt;++i)
        cout<<tr.tr[i].l<<" "<<tr.tr[i].r<<" "<<tr.tr[i].sum<<endl;
}
void dfs(int u)
{
    in[u]=++cnt;
    size[u]=1;
    vis[cnt]=u;
    for(auto &i:E[u])
    {
        dfs(i);
        size[u]+=size[i];
    }
}
void init(int n)
{
    cnt=0;
    for(int i=1;i<=n;++i)
        E[i].clear();
}
int main()
{
    int n,t,m;
    while(~scanf("%d%d",&n,&m))
    {
        init(n);
        for(int i=1;i<n;++i)
        {
            scanf("%d",&t);
            E[t].push_back(i+1);
        }
        dfs(1);
        //for(int i=1;i<=cnt;++i)
            //cout<<in[i]<<" "<<size[i]<<" "<<vis[i]<<endl;
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        int nnew=unique(b+1,b+1+n)-b-1;
        tr.init();
        tr.build(tr.rt[0],1,nnew);
        for(int i=1;i<=n;++i)
        {
            tr.rt[i]=tr.rt[i-1];
            int pos=lower_bound(b+1,b+1+nnew,a[vis[i]])-b;
            tr.update(tr.rt[i],1,nnew,pos);
        }
        //print();
        for(int i=0;i<m;++i)
        {
            scanf("%d%d",&n,&t);
            int k=upper_bound(b+1,b+1+nnew,t)-b-1;
            int l=tr.rt[in[n]-1],r=tr.rt[in[n]+size[n]-1];
            printf("%d\n",tr.query(l,r,1,nnew,k));
        }
    }
    return 0;
}

 

SCUT106 花式AC 主席树版本

标签:版本   bsp   代码   upd   ini   ret   bit   sort   int()   

原文地址:https://www.cnblogs.com/Aya-Uchida/p/11332737.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!