CodeForces - 932D Tree(树上倍增,好题)

题目链接:点击查看

题目大意:给出一棵树,初始时只有一个节点1,权值为0,后续有 n 个操作,每次操作分为两种情况:

  1. 1 u val:向树中插入一个新的节点,其父节点为 u ,权值为 val
  2. 2 u val:询问以节点 u 为起点的最长不下降子序列的长度,这里规定的最长不下降子序列需要满足以下几个条件:
    1. 以 u 为起点,每次的路线必须都是当前节点的父节点
    2. 序列中的权值和小于等于 val

题目分析:因为操作二需要每次按照要求往祖先节点上跳,我们不妨设计一下倍增来处理所需要解决的问题

  1. dp[ u ][ i ]:代表节点 u 向上经过 2^i 个权值大于等于 w[u] 的结点后的位置
  2. sum[ u ][ i ]:代表节点 u 向上经过 2^i 个权值大于等于 w[u] 后的权值和(只统计这 2^i 个数)

有了这两个数组的定义后,那么我们在插入时,可以logn维护一下这两个数组,在查询时,也可以logn获得答案,有很多细节,具体实现看代码吧:

代码:

#include<iostream>
#include<cstdio> 
#include<string>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
#include<unordered_map>
using namespace std;
 
typedef long long LL;
 
const LL inf=0x3f3f3f3f3f3f3f3f;
 
const int N=4e5+100;

LL last,dp[N][25],sum[N][25],w[N],cur;

void add(LL u,LL val)
{
	u^=last;
	val^=last;
	w[++cur]=val;
	if(w[cur]<=w[u])//处理dp[u][0]
		dp[cur][0]=u;
	else
	{
		for(int i=20;i>=0;i--)
			if(w[cur]>w[dp[u][i]])
				u=dp[u][i];
		dp[cur][0]=dp[u][0];
	}
	if(dp[cur][0]==0)//处理sum[u][0]
		sum[cur][0]=inf;
	else
		sum[cur][0]=w[dp[cur][0]];
	for(int i=1;i<=20;i++)//维护dp数组和sum数组
	{
		dp[cur][i]=dp[dp[cur][i-1]][i-1];
		if(dp[cur][i]==0)
			sum[cur][i]=inf;
		else
			sum[cur][i]=sum[cur][i-1]+sum[dp[cur][i-1]][i-1];
	}
}

LL query(LL u,LL val)
{
	u^=last;
	val^=last;
	if(w[u]>val)
		return 0;
	LL ans=1;
	val-=w[u];
	for(int i=20;i>=0;i--)//统计答案
	{
		if(val>=sum[u][i])
		{
			val-=sum[u][i];
			ans+=(1<<i);
			u=dp[u][i];
		}
	}
	return ans;
}

void init()//初始化sum数组到所有不可能到达的位置为无穷大
{
	w[0]=inf;
	w[1]=0;
	last=0;
	cur=1;
	for(int i=0;i<=20;i++)
		sum[1][i]=inf;
}

int main()
{
//	freopen("input.txt","r",stdin);
//	ios::sync_with_stdio(false);
	init();
	int n;
	scanf("%d",&n);
	while(n--)
	{
		LL op,p,q;
		scanf("%lld%lld%lld",&op,&p,&q);
		if(op==1)
			add(p,q);
		else
			printf("%lld\n",last=query(p,q));
	}
 
	
	
	
	
	
	
	
	
	
	return 0;
}
发布了549 篇原创文章 · 获赞 16 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_45458915/article/details/104076907