P5384 [Cnoi2019] 雪松果树
P5384 [Cnoi2019] 雪松果树
题目背景
幻想乡,冬。
一年一度,生长在高山上的雪松果树又结果了。
Cirno 不知从哪弄到了
Cirn o因为以后吃不到雪松果而感到忧愁,于是决定种在美丽的雾之湖畔。
第一天,发芽。
第二天,雪松果树长成了一颗参天大树, 上面长满了雪松果。
Cirno 在雪松果成熟之前早有一些问题想知道,但现在她忙于收集雪松果,就把问题丢给了你。
题目描述
雪松果树是一个以
除此之外, Cirno还有
我们定义:
节点
的 -father 为 路径 (不含 u)上距 u 最近的节点 节点
的 -father 为 节点 「 的 -father」 的 1-father 节点
的 -son 为所有 -father 为 的节点 节点
的 -cousin 为 节点「 的 -father」的 -son (不包含 本身)
数据范围:
对于 100% 的数据
Solution:
说句闲话:
感谢 red_fire 大神的推荐。
看题面时:水题。
口胡时:水题。
然而爆唐的我本人总能把自己口胡的思路实现得爆炸就是了。
言归正传:
我们要实现的东西其实很简单,就是对于一个点
实现:
我们可以维护一个桶
所以我们要将询问离线并挂到
Code:
#include<bits/stdc++.h> const int lg=20; const int N=1e6+6; using namespace std; int n,m,cnt; int dep[N],bac[N],f[N][lg+1],bit[lg+5],ans[N]; vector<int> E[N]; vector<tuple<int,int> > Q[N]; void dfs(int x,int fa) { dep[x]=dep[fa]+1; for(auto [k,id] : Q[x]){ans[id]-=bac[dep[x]+k];} for(int y : E[x])dfs(y,x);bac[dep[x]]++; for(auto [k,id] : Q[x]){ans[id]+=bac[dep[x]+k];} } inline int k_fa(int x,int k){ for(int i=lg;i>=0;i--)if(k>=bit[i])k-=bit[i],x=f[x][i];return x;} void work() { cin>>n>>m;bit[0]=1;for(int i=1;i<=lg;i++)bit[i]=bit[i-1]<<1; for(int u=2;u<=n;u++){scanf("%d",&f[u][0]);E[f[u][0]].emplace_back(u);} for(int x=1;x<=n;x++)for(int j=1;j<=lg;j++)f[x][j]=f[f[x][j-1]][j-1]; for(int i=1,x,k;i<=m;i++) { scanf("%d%d",&x,&k); int y=k_fa(x,k);ans[i]=-1; if(!y||k==0){ans[i]=0;continue;} Q[y].emplace_back(k,i); } dfs(1,0); for(int i=1;i<=m;i++)printf("%d ",ans[i]); } int main() { work();return 0; }