首页 > 其他分享 >CF1006E Military Problem 题解

CF1006E Military Problem 题解

时间:2024-01-11 17:11:07浏览次数:23  
标签:遍历 int 题解 前序 leq Military Problem thinspace size

CF1006E Military Problem 题解

题意

给定一颗有 \(n \thinspace (2 \leq n \leq 2 \times 10^5)\) 个节点的树,树根为 \(1\)。

对于每个节点 \(i \thinspace (2 \leq i \leq n)\) 都有它的父节点 \(p_i\),并且每个节点的子节点都是按从小到大的顺序排列的的。

有 \(q \thinspace (1 \leq q \leq 2 \times 10^5)\) 个询问,每次询问都有一个 \(u_i,k_i \thinspace (1 \leq u_i,k_i \leq n)\),输出以 \(u_i\) 为根的子树的前序遍历中排名为 \(k_i\) 的元素。

如果子树中没有 \(k_i\) 个节点则输出 \(-1\)。

暴力做法

对于每个询问 \(i\) 的 \(u_i\),直接在以 \(u_i\) 为根的子树中做前序遍历,取第 \(k_i\) 个被遍历到的元素作为答案即可。

由于每次遍历都有可能遍历整棵树,所以时间复杂度最坏为 \(O(nq)\),会超时。

正解

继续在暴力做法上寻找优化方法。

如果我们画图会发现,一棵子树内前序遍历的编号是连续的。

所以我们就可以利用这一性质,在树的前序遍历上做询问。

先对整棵树跑一边前序遍历并将其记录下来。

在询问时,先找到 \(u_i\) 在前序遍历中的下标 \(o\),再找寻前序遍历中以下标 \(o\) 开始的第 \(k_i\) 元素的下标 \(l\)。

最终前序遍历中下标为 \(l\) 的元素即为所求答案。

对于输出 \(-1\) 的情况,只需要记录一下以 \(i \thinspace (1 \leq i \leq n)\) 为根的子树大小 \(size_i\)。在询问时,判断是否 \(size_{u_i} < k_i\) 即可。

由于预处理时间复杂度为 \(O(n)\),每次询问时间复杂度为 \(O(1)\),所以最终时间复杂度为 \(O(n+q)\),可以通过测试。

代码

#include<stdio.h>
#include<vector>
const int N=2e5+5;
std::vector<int> v[N];
int n,m,num[N],cnt,kth[N],size[N];
void build(int u){//预处理
	num[++cnt]=u;//前序遍历编号对应元素
	kth[u]=cnt;//元素对应编号
	size[u]=1;//子树大小
	for(auto son:v[u]) build(son),size[u]+=size[son];
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=2,x;i<=n;i++) scanf("%d",&x),v[x].emplace_back(i);
	build(1);
	int x,y;
	while(m--){
		scanf("%d%d",&x,&y);
		if(size[x]<y) puts("-1");
		else printf("%d\n",num[kth[x]+y-1]);
	}
	return 0;
}

标签:遍历,int,题解,前序,leq,Military,Problem,thinspace,size
From: https://www.cnblogs.com/gevenfeng/p/17959033

相关文章

  • 【题解】CatOJ C0458C 滑动窗口定期重构
    标题trick的名字我也不知道是什么,就这样吧。link。首先有显然的dp式子:\(f(i)=\min\{f(j)\times\max\{a_{j+1},\dots,a_i\}\}\)。考虑怎么去优化它。有显然的\(\mathcalO(n\logn)\):考虑线段树优化dp。用增的单调栈维护\(a\),若每次弹出顶部一个下标\(p\),则\([p+1,i......
  • 1.11模拟赛 T1题解
    简要题意\(n\le10^3,\sumK_i\le3\times10^5\)思路首先容易想到一个暴力DP,\(f_{l,r,x}\)表示区间中最大值为\(x\)的最大值稍微想亿下可以发现如果这个位置选的不是区间最大值的话,答案一定不优所以我们可以直接\(f_{l,r}\)DP转移,但复杂度还是没变,我们把柿子列出来\(......
  • AT_joisc2018_b 题解
    AT_joisc2018_b题解传送门题意有一个以原点为中心的正方形,有\(n(n\le100)\)条不在正方形内部的线段,你需要画一些不在正方形内部的线段,使得这些线段可以把正方形围起来,要求最小化你画的线段的长度和。思路我们需要画出一条闭合折线,并且能够把正方形包围。考虑我们一定是......
  • 1.11模拟赛 T2题解
    简要题意每个点有一定概率向前面的点连边,求两点之间距离的期望思路推柿子code#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineN1000005intn,m,u,v;constintmod=1e9+7;inta[N],sum[N],c[N],dep[N],s[N],f[N],g[N],h[N];intksm(intx......
  • P4103 [HEOI2014] 大工程 题解
    题目链接:大工程先考虑只有一次查询,很显然我们可以暴力树上dp处理出答案。对于每个节点而言,有:容易看出类似点分治逐个遍历子树计算前面一堆子树对后面子树的贡献思想,我们可以很容易的知道:对于路径总和,显然多了一段新的贡献,这段贡献为当前关键点和前面点多的一段\(2\)号路......
  • 《算法竞赛》题解---三分
    三分法模板三分法#include<bits/stdc++.h>#defineeps1e-8//或者constdoubleeps=1e-8;--主要是doubleusingnamespacestd;intn;doublea[15],l,r;doublecheck(doublex){ doubleans=0; for(inti=n;i>=0;i--) ans=ans*x+a[i];//秦九韶公式 returnans;}......
  • P4093 [HEOI2016/TJOI2016] 序列 题解
    题目链接:序列对于LIS问题,很显而易见的有dp方程为:\[dp_i=\max{dp_j}+1\(j<i,a_j\lea_i)\text{dp表示以某个位置结尾的最长LIS}\]本题考虑到对于转移的两位置,如果能从\(j\rightarrowi\),那么在以上条件成立的基础情况下,我们由于可以更改二者中的任意一个值(因为同一......
  • 2023 百度之星决赛题解
    T4传信游戏建反向边,从入度为\(0\)的结点开始搜T5喵喵卫士,全靠你了\(\star\)考虑暴力枚举每个点的深度,发现只要知道相邻两层的深度就能用组合数算方案数,自然想到按层DP,把上一层的点数记到状态里赛时做法按深度从小到大DP的话想要记录每个点是否被用过,以保证深度达到上......
  • P3203 弹飞绵羊 题解
    QuestionP3203[HNOI2010]弹飞绵羊一条直线上摆着\(n\)个弹簧,每个弹簧有一个弹力系数\(k_i\),当绵羊走到第\(i\)个弹簧时,会被弹到第\(i+k_i\)个弹簧,如果\(i+k_i>n\)则会被弹飞,有两个操作1x查询\(x\)处的绵羊经过几次会被弹飞2xy把\(x\)处的弹力系数改成......
  • P1307题解
    思路1.定义及输入原数/反转后的数intn,cnt=0;//反转后的数一定要归零!cin>>n;2.用while循环反转while(n!=0){//只要n还没有被分解完,就继续分解cnt=cnt*10+n%10;//cnt每次*10再加上分离出的数位(*10为了防0)n/=10;//n减一位}3.输出cout<<cnt;至此,这道题就做完......