hdu多校第三场 Solve this interesting problem (5323 线段树模拟 + DFS)

Solve this interesting problem

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1810    Accepted Submission(s): 542


Problem Description
Have you learned something about segment tree? If not, don’t worry, I will explain it for you.
Segment Tree is a kind of binary tree, it can be defined as this:
- For each node u in Segment Tree, u has two values: Lu and Ru .
- If Lu=Ru , u is a leaf node.
- If LuRu , u has two children x and y,with Lx=Lu , Rx=Lu+Ru2 , Ly=Lu+Ru2+1 , Ry=Ru .
Here is an example of segment tree to do range query of sum.



Given two integers L and R, Your task is to find the minimum non-negative n satisfy that: A Segment Tree with root node's value Lroot=0 and Rroot=n contains a node u with Lu=L and Ru=R .
 

Input
The input consists of several test cases.
Each test case contains two integers L and R, as described above.
0LR109
LRL+12015
 

Output
For each test, output one line contains one integer. If there is no such n, just output -1.
 

Sample Input
  
  
6 7 10 13 10 11
 

Sample Output
  
  
7 -1 12
 

题目大意:

给定一个区间[L,R],求根结点的右端点最少为多少,才可以满足区间[L,R]是这个线段树的一个结点。可以的话输出根结的右端点的最小值,不可以的话输出-1.

解题思路:

换个思路我们可以从下到上递归到根结点,也就是L = 0的时候递归结束,递归的时候一共可能出现四种情况,画图就可以知道,由于父结点是子节点区间长度的两倍,所以一直往上递归可以到根结点,每次更新区间中的右端点,就可以得出结果。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

#define inf 1e16
long long res; //全局变量统计最小值 
long long m,n;
 
void dfs(long long ll,long long rr)
{
	if(rr >= res || rr > 2 * n) //rr必须小于res才有更新的必要,父结点右端点不会超过两倍子结点右端点的值
		return;
	if(ll == 0) //到了根结点了
	{
		res = rr;
		return;	
	} 
	long long temp = rr - ll + 1; //区间长度 
	if(ll - temp >= 0)
		dfs(ll - temp,rr); //左区间扩大 
	if(ll - temp >= 1)
		dfs(ll - temp - 1,rr); //左区间扩大
	dfs(ll,rr+temp-1); //右区间扩大 
	dfs(ll,rr+temp); //右区间扩大 
}

int main()
{
	while(scanf("%lld%lld",&m,&n) != EOF)
	{
		res = inf; //初始很小 
		dfs(m,n); //左区间,右区间
		if(res == inf) printf("-1\n");
		else
			printf("%lld\n",res);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值