题意:
给出一个点权树以$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;
}