HUD 5323 Solve this interesting problem dfs剪枝搜索,重构线段树

Solve this interesting problem


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 问知否存在这样的线段树 [0 , n] 使得n最小并且包含区间 [L, R]
 * dfs向上搜索, 由于该区间可能是父节点的左儿子或右儿子,分类讨论,注意取整时可能
 * 导致求得的L 或 R 与实际相差1 , 将这四种情况都考虑即可。
 * 注意剪枝, 在线段树中,每个节点的左儿子区间 = 右儿子区间 或者 右儿子加一
 */
 
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;

ll ans = -1;

void dfs(ll l, ll r) {
    if(l == 0) {
        if(ans == -1) {
            ans = r;
        }
        else {
            ans = min(ans, r);
        }
        return ;
    }
    if(l < 0) return ;
    if(ans != -1 && r >= ans) return ;
    if(l < r-l+1) return; // 剪枝
    dfs(l, 2*r - l);
    dfs(l, 2*r - l + 1);
    dfs(2*l - r - 1, r);
    dfs(2*l - r - 2, r);
}

int main() {
    ios::sync_with_stdio(false);
    ll l, r;
    while(cin >> l >> r) {
        if(l == r) {
            cout << l << endl;
            continue;
        }
        ans = -1;
        dfs(l, r);
        cout << ans << endl;
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值