[dfs] Jzoj P4208 线段树什么的最讨厌了

 

Description

小Y 最近学习了线段树,但是由于她的智商比较低,运用的还不是很熟练。于是小R 给了她一点练习题训练,其中有一道是这样的。
这是小R 写的线段树的一段建树代码:

只要调用buildtree(1,0,n) 就可以得到一颗线段树了。显然,一颗线段树一共有O(n) 个节点,因为每一个节点都代表了一个不同的区间,所以线段树上一共出现了O(n) 个不同的区间。
现在小R 给了你一个区间[l; r],他想要你告诉他一个最小的n 使得区间[l; r] 出现在了用buildtree(1,0,n) 建出来的线段树中。
 

Input

第一行输入一个正整数T 表示数据组数。
接下来T 行每行三个整数L;R; lim 表示一组询问,如果对于所有的0 <= n <= lim 都不存在满足条件的解,输出-1 即可。

Output

对于每组询问输出一个答案。
 

Sample Input

2
0 5 10
6 7 10

Sample Output

5
7
 

Data Constraint

 

题解

  • 题目大意:给定一个区间问,在满足右区间<=lim的情况下,包含该区间的线段树的最小左右区间为多少
  • 那么可以考虑一下,我们打线段树的时候,二分一个mid,然后分两部分走
  • 这样我们考虑反着往上推,那就会出现四种情况
  • ①上一个区间的[l,r]可以整除2,然后当前走的是左区间
  • ②上一个区间的[l,r]可以整除2,然后当前走的是右区间
  • ③上一个区间的[l,r]不可以整除2,然后当前走的是左区间
  • ④上一个区间的[l,r]不可以整除2,然后当前走的是右区间
  • 推到l==0的时候就是ans,取最小值就好了
  • 注意特判一些坑爹的地方

代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #define ll long long 
 4 using namespace std;
 5 const ll N=0x7fffffff;
 6 ll ans=0,m,L,R,lim;
 7 void dfs(ll  l,ll  r)
 8 {   
 9     if (r>lim||r>ans&&ans!=-1||l<0) return;
10     if (l==0) { if (ans==-1||ans>r) ans=r; return; }
11     if (2*l<r)return;
12     if (l<2*r-l) dfs(l,2*r-l);
13     if (l<2*r-l+1) dfs(l,2*r-l+1);
14     if (r>2*l-r-2) dfs(2*l-r-2,r);
15     if (r>2*l-r-1) dfs(2*l-r-1,r);
16 }
17 int main()
18 {
19     cin>>m;
20     for (ll i=1;i<=m;i++)
21     {
22         cin>>L>>R>>lim,ans=-1,dfs(L,R);
23            cout<<ans<<endl;
24     }
25     return 0;
26 }

 

posted @ 2019-01-21 15:44  BEYang_Z  阅读(203)  评论(0编辑  收藏  举报