首页 > 其他分享 >CF208E 题解

CF208E 题解

时间:2024-07-18 12:20:06浏览次数:11  
标签:idx int 题解 tr mid dep CF208E define

Blood Cousins

前置知识:线段树合并。

我们先把题目转化一下。这里先设 \(v\) 的 \(p\) 级祖先为 \(u\),事实上要求的东西就是 \(u\) 的 \(p\) 级后代的个数减 \(1\),减 \(1\) 是因为要把自己减去。显然这个目标点 \(t\) 要满足两个要求:

  • \(t\) 在 \(u\) 子树内。

  • 设 \(dep_u\) 表示 \(u\) 的深度,则 \(dep_u+p=dep_t\)。

于是我们对每个点建一棵权值线段树,维护深度,然后把询问离线下来,如果这个点有询问,我们就在合并后的权值线段树内查找目标深度的点的个数即可。

然后就说完了,直接看一下代码:

#include<bits/stdc++.h>
#define int long long
#define N 100005
#define M 200005
#define K 23
#define pii pair<int,int>
#define x first
#define y second
using namespace std;
int n,m,tot;
int h[N],e[M],ne[M],idx;
int fa[N][K],dep[N],res[N],rt[N];
vector<int>root;
vector<pii>ask[N];
void add(int a,int b){
	e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void dfs1(int u,int f){
	dep[u]=dep[f]+1;
	fa[u][0]=f;
	for(int i=1;i<K;i++){
		fa[u][i]=fa[fa[u][i-1]][i-1];
	}
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==f)continue;
		dfs1(j,u);
	}
}
int get(int u,int k){
	for(int i=K-1;~i;i--){
		if(k>>i&1){
			u=fa[u][i];
		}
	}
	return u;
}
struct node{
	int l,r,sum;
}tr[N<<5];
void pushup(int u){
	tr[u].sum=tr[tr[u].l].sum+tr[tr[u].r].sum;
}
void modify(int &u,int l,int r,int p){
	if(!u)u=++tot;
	if(l==r){
		tr[u].sum++;
		return;
	}
	int mid=l+r>>1;
	if(p<=mid)modify(tr[u].l,l,mid,p);
	else modify(tr[u].r,mid+1,r,p);
	pushup(u);
}
int merge(int x,int y,int l,int r){
	if(!x||!y)return x+y;
	if(l==r){
		tr[x].sum+=tr[y].sum;
		return x;
	}
	int mid=l+r>>1;
	tr[x].l=merge(tr[x].l,tr[y].l,l,mid);
	tr[x].r=merge(tr[x].r,tr[y].r,mid+1,r);
	pushup(x);
	return x;
}
int qry(int u,int l,int r,int p){
	if(l==r)return tr[u].sum;
	int mid=l+r>>1;
	if(p<=mid)return qry(tr[u].l,l,mid,p);
	else return qry(tr[u].r,mid+1,r,p);
}
void dfs2(int u){
	modify(rt[u],1,n,dep[u]);
	for(int i=h[u];~i;i=ne[i]){
		int j=e[i];
		if(j==fa[u][0])continue;
		dfs2(j);
		rt[u]=merge(rt[u],rt[j],1,n);
	}
	for(auto eu:ask[u]){
		res[eu.y]=qry(rt[u],1,n,eu.x)-1;
	}
}
signed main(){
	cin>>n;
	memset(h,-1,sizeof h);
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		if(x)add(x,i),add(i,x);
		else root.push_back(i);
	}
	for(auto i:root){
		dep[i]=1;
		dfs1(i,0);
	}
	cin>>m;
	for(int i=1;i<=m;i++){
		int x,k;
		cin>>x>>k;
		int p=get(x,k);
		if(p==0){
			res[i]=0;
			continue;
		}
		ask[p].push_back({k+dep[p],i});
	}
	for(auto i:root){
		dfs2(i);
	}
	for(int i=1;i<=m;i++){
		cout<<res[i]<<' ';
	}
	return 0;
}

标签:idx,int,题解,tr,mid,dep,CF208E,define
From: https://www.cnblogs.com/zxh923aoao/p/18309266

相关文章

  • P3242 接水果 题解
    Statement树,给\(m\)条带权路径\((a,b,v)\),\(q\)次询问包含\((u,v)\)的路径中的第\(k\)小权值.Solution好题!这篇题解延伸出了很多东西。首先路径的包含关系转为矩形(二维限制关系)是比较显然的.具体地,\((u,v)\)包含\((a,b)\)有两种情况:\(u,v\)无祖先关系:\(a\)在......
  • P1912 [NOI2009] 诗人小G 题解
    我们设\(s_i\)表示前\(i\)个句子的长度之和,这样就有dp\[f_i=\min_{j<i}\big\{f_j+|s_i-s_j+i-j-1-L|^P\big\}\]我们设\(w(l,r)=|s_r-s_l+r-l-1-L|^P\),如果\(w\)满足四边形不等式,则原dp具有决策单调性。设\(u=(s_i+i)-(s_j+......
  • [题解]P1452 【模板】旋转卡壳 | [USACO03FALL] Beauty Contest G
    P1452【模板】旋转卡壳|[USACO03FALL]BeautyContestG旋转卡壳模板题。凸包用的是Andrew算法,就不详述了,具体可以查查资料了解,但提一嘴Andrew算法的一些细节问题:Andrew算法的一些细节Andrew算法的模板代码如下:sort(a+1,a+1+n,cmp);st[++top]=1;for(inti=2;i<=n;i++){ ......
  • 【数学建模】——多领域资源优化中的创新应用-六大经典问题解答
    目录题目1:截取条材题目 1.1问题描述1.2数学模型1.3求解1.4解答题目2:商店进货销售计划题目2.1问题描述2.2数学模型2.3求解2.4解答题目3:货船装载问题题目3.1问题重述 3.2数学模型3.3求解3.4解答题目4:城市消防站选址问题 题目4.1问题重述4.2......
  • 题解:P10733 [NOISG2019 Prelim] Lost Array
    题解:P10733[NOISG2019Prelim]LostArray思路对于任意\(\min(X_{A_{i}},X_{B_{i}})=C_{i}\)。只要让\(X_{A_{i}}\)与\(C_{i}\)取\(\max\)值。\(X_{B_{i}}\)与\(C_{i}\)取\(\max\)值。这样可以让\(\min(X_{A_{i}},X_{B_{i}})\)绝对是\(C_{i}\)。对于为赋值......
  • 题解:P10781 【MX-J1-T1】『FLA - III』Spectral
    本题的主要思路就是数学。首先,让我们先来打一个表。\(i\)\(1\)\(2\)\(3\)\(4\)\(\dots\)\(T_{i}\)\(k\)\(1.5k\)\(1.5k\)\(1.375k\)\(\dots\)易用肉眼看见,自\(T_{3}\)之后数越来越小,于是我们大胆猜测,若\(n\ne1\),则它的最大值是\(1.5k\)否则\(k\)。......
  • 题解 P1031 [NOIP2002 提高组] 均分纸牌
    link贪心题中描述每一堆牌只能移动若干张牌到相邻的牌堆上确定了局部最优解必定能推导出全局最优解。易知均分完后,每堆牌的数量都为纸牌总数的平均数\(\mathrm{arg}\)。所以我们可以预处理每堆牌跟\(\mathrm{arg}\)的差距for(inti=1;i<=n;++i)sum+=a[i];......
  • [题解]POJ3675 Telescope——求多边形与圆相交部分的面积
    POJ3675Telescope题意简述多测。每次给定一个\(N\)边形(保证相邻输入的顶点在多边形上也是邻接的),再给定一个以\((0,0)\)为圆心,半径为\(r\)的圆。请计算出多边形和圆相交部分的面积(保留\(2\)位小数)。\(3\leN\le50\)\(0.1\ler\le1000\)\(-1000\lex_i,y_i\le1000\)。......
  • ABC361-D题解
    背景保佑LC能来一中。题意给你一个长度为\(n\)的初始字符串和目标字符串,都由W和B两种字符构成。现在初始字符串末尾接有两个空格字符,每次你可以在该字符串中选出连续两个非空格字符,并把它们按顺序与两个空格交换位置。问最少需要几步能得到目标字符串。分析首先如果两......
  • ABC361-C题解
    背景昨天打比赛的时候查了中考分,心快停跳了。题意从\(n\)个数字中删除\(k\)个数字,问剩下的数字中极差的最小值。分析首先把这\(n\)个数字排序,然后问题就可以转化为求这\(n\)个数字中所有长度为\(n-k\)的连续子段的极差的最小值。采用尺取法,可以从\(1\)开始枚举......