题意:
给出若干棵树,q次询问,每次询问某结点n向上k步的父节点的子树中有多少个和n是兄弟结点(深度相同)
ps:这里的题意是将问题简化过后的
假设现在只有一棵树,首先考虑结点的子树如何确定,dfs序可以解决,再考虑向上k步的lca如何解决,倍增法求lca(弱不会),由于只会树剖向上爬,外加上树剖可以直接处理dfs序,所以就写树剖了…对于子树内符合条件的结点,只需要开
105
个深度的vector存一下dfs序,然后每次lower_bound和upper_bound就能找到对应答案…做法没什么不对,就是从来没这样搞过,好在1A,codeforces题目还是神奇…
仔细想想这不就是在XJB搞嘛…..
#include<cstring>
#include<string>
#include<iostream>
#include<queue>
#include<cstdio>
#include<algorithm>
#include<map>
#include<cstdlib>
#include<cmath>
#include<vector>
//#pragma comment(linker, "/STACK:1024000000,1024000000");
using namespace std;
#define INF 0x3f3f3f3f
#define maxn 200003
int a[maxn];
int fir[maxn],nex[maxn],e_max,v[maxn];
int in[maxn],out[maxn];
int son[maxn],fa[maxn],deep[maxn],top[maxn],siz[maxn],cnt,tot;
int inv[maxn];
vector<int>vec[100005];
void init_()
{
memset(fir,-1,sizeof fir);
memset(son,-1,sizeof son);
e_max=0;
cnt=0;
tot=0;
}
void add_edge(int s,int t)
{
int e=e_max++;
v[e]=t;
nex[e]=fir[s];
fir[s]=e;
}
void dfs1(int k,int pre,int d)
{
deep[k]=d;
fa[k]=pre;
siz[k]=1;
for(int i=fir[k];~i;i=nex[i])
{
int e=v[i];
if(e!=pre)
{
dfs1(e,k,d+1);
siz[k]+=siz[e];
if(son[k]==-1||siz[son[k]]<siz[e]) son[k]=e;
}
}
}
void dfs2(int k,int sp)
{
top[k]=sp;
in[k]=++tot;
inv[tot]=k;
vec[deep[k]].push_back(in[k]);
out[k]=in[k];
if(son[k]==-1) return;
dfs2(son[k],sp);
out[k]=max(out[k],out[son[k]]);
for(int i=fir[k];~i;i=nex[i])
{
int e=v[i];
if(e!=fa[k]&&e!=son[k])
{
dfs2(e,e);
out[k]=max(out[k],out[e]);
}
}
}
int query(int s,int k)
{
s=fa[s];
int f1=top[s];
while(k)
{
int d=in[s]-in[f1]+1;
if(k>d)
{
k-=d;
s=fa[f1];
f1=top[s];
}
else
{
s=inv[ in[s]-k+1 ];
break;
}
}
return s;
}
int main()
{
init_();
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]) add_edge(a[i],i),add_edge(i,a[i]);
}
for(int i=1;i<=n;i++)
{
if(!a[i])
{
dfs1(i,-1,0);
dfs2(i,i);
}
}
for(int i=1;i<=n;i++)
{
sort(vec[i].begin(),vec[i].end());
}
int q;
scanf("%d",&q);
while(q--)
{
int a,b;
scanf("%d%d",&a,&b);
if(deep[a]<b||b==0)
{
printf("0 ");
continue;
}
int lca=query(a,b);
int d=deep[a];
int l=lower_bound(vec[d].begin(),vec[d].end(),in[lca])-vec[d].begin();
int r=upper_bound(vec[d].begin(),vec[d].end(),out[lca])-vec[d].begin();
printf("%d ",r-l-1);
}
}
/*
9
0 1 2 3 4 4 3 2 1
*/