(补题)A - Big binary tree(map储存二叉树,完全二叉树,树型dp)

A - Big binary tree

 HDU - 6161

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 849    Accepted Submission(s): 323


 

Problem Description


You are given a complete binary tree with n nodes. The root node is numbered 1, and node x's father node is ⌊x/2⌋. At the beginning, node x has a value of exactly x. We define the value of a path as the sum of all nodes it passes(including two ends, or one if the path only has one node). Now there are two kinds of operations:
1.  change u x Set node u's value as x(1≤u≤n;1≤x≤10^10)
2.  query u Query the max value of all paths which passes node u.

 

 

Input

There are multiple cases.
For each case:
The first line contains two integers n,m(1≤n≤10^8,1≤m≤10^5), which represent the size of the tree and the number of operations, respectively.
Then m lines follows. Each line is an operation with syntax described above.

 

 

Output

For each query operation, output an integer in one line, indicating the max value of all paths which passes the specific node.

 

 

Sample Input

 

6 13 query 1 query 2 query 3 query 4 query 5 query 6 change 6 1 query 1 query 2 query 3 query 4 query 5 query 6

 

 

Sample Output

 

17 17 17 16 17 17 12 12 12 11 12 12

 

 

Source

2017 Multi-University Training Contest - Team 9

 

题意:

有一颗二叉树,其提供查询和修改两种操作。一是query i即查询所有经过i节点的路径的值的最大值,二是change u x将u节点的值改为x

思路:

这个题目大概需要解决这么几个问题:

1、二叉树的规模太大了,无法直接用数组储存

2、如何寻找经过某节点的路径的最大值

首先解决第一个问题:

由于除了修改的值外,所有节点的值即是其编号,因此可以使用一个map来仅仅储存被修改的值

然后是第二个问题:

通过简单的分析我们可以知道,可以达到最大值的路径必定是以待查询节点向上的某节点的另一子节点的向下走所能达到的最大值,加上待查询节点到这个节点所经过的节点的值加上待查询节点向下走所能达到的最大值。

那么如何得到一个节点向下走所能得到的最大路径?

在保证能走到该节点能达到最深层的前提下尽量向右走即可(因为向下和向右均是较大的值,但是向下增加得更快一点)

 

需要注意的是每次修改之后被修改节点以上的向下走所能达到的最大值都需要修改。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;

typedef long long LL;
int size;
map<int,LL> tree;
map<int,LL> maxn;
#define val(x) (tree.count(x)?tree[x]:x)
#define mvl(x) (x<<1)
//向左下移动 
#define mvr(x) (x<<1|1)
//向右下移动 
#define mvu(x) (x>>1)
//向上移动 
#define from(x) ((x&1)?(x<<1):(x<<1|1))

LL solve(int x)
{
	if(x>size) return 0;
	if(maxn.count(x)) return maxn[x];	
	LL ans=0;
	int ori=x;
	int deepl=0,deepr=0;
	while(mvl(ori)<=size)
	{
		ori=mvl(ori);
		++deepl;
	}
	ori=x;
	while((mvr(ori))<=size)
	{
		ori=(mvr(ori));
		++deepr;
	}
	if(deepl!=deepr) ori=size;
	while(ori>=x)
	{
		ans+=ori;
		ori=mvu(ori);
	}
	//maxn[x]=ans;
	return ans;
}
LL found(int x)
{
	LL ans=solve(mvr(x))+solve(mvl(x))+val(x);
	//cout<<(val(x)+solve(mvr(x))+solve(mvl(x)))<<endl;
	int ori=x;
	LL goup=0;
	while(mvu(x))
	{
		
		goup+=val(mvu(x));
		if(x&1)
		{
			x=mvu(x);
			ans=max(ans,solve(ori)+goup+solve(mvl(x)));
			//cout<<solve(ori)<<' '<<mvl(x)<<' '<<solve(mvl(x))<<' '<<goup<<endl;
		}
		else
		{
			x=mvu(x);
			ans=max(ans,solve(ori)+goup+solve(mvr(x)));
			//cout<<solve(ori)<<' '<<mvr(x)<<' '<<solve(mvr(x))<<' '<<goup<<endl;
		}
		
	}
	
	return ans;
}
void change(int a,LL b)
{
	maxn[a]=max(solve(mvr(a)),solve(mvl(a)))+b;
	tree[a]=b;
	while(mvu(a))
	{
		a=mvu(a);
		maxn[a]=max(solve(mvl(a)),solve(mvr(a)))+val(a);
	}
}
int main()
{
	int n;
	int x,a;LL b;
	while(cin>>size>>n)
	{
		maxn.clear();
		tree.clear();
		string str;
		int i;
		for(i=0;i<n;i++)
		{
			cin>>str;
			if(str=="query")
			{
				cin>>x;
				cout<<found(x)<<endl;
			}
			else{
				cin>>a>>b;
				change(a,b);
			}
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值