hdu5323 Solve this interesting problem(DFS关于线段树中的一些性质和规律)
Solve this interesting problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1905 Accepted Submission(s): 573
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 Lu≠Ru, 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.
![hdu5323 Solve this interesting problem(DFS关于线段树中的一些性质和规律) hdu5323 Solve this interesting problem(DFS关于线段树中的一些性质和规律)](/default/index/img?u=aHR0cHM6Ly9waWFuc2hlbi5jb20vaW1hZ2VzLzE3Mi85MDdlZTI1MWY3M2E1NGE2ZDM4YWE1NTA3YTgxYzA5NC5KUEVH)
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=ncontains a node u with Lu=L and Ru=R.
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 Lu≠Ru, 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=ncontains 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.
0≤L≤R≤109
LR?L+1≤2015
Each test case contains two integers L and R, as described above.
0≤L≤R≤109
LR?L+1≤2015
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
题意:一个线段树所有叶子节点编号为0~n,给出l和r,求出最小的n使得存在一个节点的左值等于l,右值等于r
关于线段树的一些性质和规律:如果存在一个节点其左值为l右值为r,那么他的父亲节点的左右值有四种可能,即
[l,2*l+1]
[l,2*r]
[2*(l-1)-r,r]
[2*(l-1)-r+1,r]
所以题目给出l和r的值后,按着四个方向进行DFS,剪枝条件:
当已找到一个合适的mi值后,r>=mi的值,return(如果只判断r>mi的话就会超时)
l<0 那肯定return了
该节点的区间长度即 r-l+1 如果大于 l 则return, 原因:将(l,r)看做这个线段树的右子树的话,左子树的长度即为l,右子树的长度为(r-l+1) 线段树性质:左子树区间长度大于等于右子树的区间长度
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
long long mi;
long long L,R;
long long minn(long long a,long long b){
return a<b?a:b;
}
void DFS(long long l,long long r){
if(l==0){
if(mi==-1) mi=r;
else mi=minn(mi,r);
}
if(mi!=-1&&r>=mi) return;
if(l<0) return;
if(r-l+1>l) return ;
DFS((l-1)*2-r,r) ;
DFS((l-1)*2+1-r,r) ;
DFS(l,r*2-l) ;
DFS(l,r*2+1-l) ;
}
int main(int argc, char *argv[])
{
while(scanf("%lld%lld",&L,&R)!=EOF){
mi=-1;
DFS(L,R);
printf("%lld\n",mi);
}
return 0;
}