【Codeforces Round 276 (Div 2)C】【讨论】Bits [l,r]范围内第1个数最多数中最小的那个

C. Bits
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Let's denote as  the number of bits set ('1' bits) in the binary representation of the non-negative integer x.

You are given multiple queries consisting of pairs of integers l and r. For each query, find the x, such that l ≤ x ≤ r, and is maximum possible. If there are multiple such numbers find the smallest of them.

Input

The first line contains integer n — the number of queries (1 ≤ n ≤ 10000).

Each of the following n lines contain two integers li, ri — the arguments for the corresponding query (0 ≤ li ≤ ri ≤ 1018).

Output

For each query print the answer in a separate line.

Sample test(s)
input
3
1 2
2 4
1 10
output
1
3
7
Note

The binary representations of numbers from 1 to 10 are listed below:

110 = 12

210 = 102

310 = 112

410 = 1002

510 = 1012

610 = 1102

710 = 1112

810 = 10002

910 = 10012

1010 = 10102


#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre(){freopen("c://test//input.in","r",stdin);freopen("c://test//output.out","w",stdout);}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1,class T2>inline void gmax(T1 &a,T2 b){if(b>a)a=b;}
template <class T1,class T2>inline void gmin(T1 &a,T2 b){if(b<a)a=b;}
const int N=0,M=0,Z=1e9+7,ms63=1061109567;
int n;
LL l,r;
int a[64],b[64];
void get(LL x,int a[])
{
	while(x)
	{
		a[++a[0]]=x&1;
		a[63]+=x&1;
		x>>=1;
	}
}
LL solve()
{
	if(l==r)return r;
	MS(a,0);get(l,a);
	MS(b,0);get(r,b);
	if(b[0]==b[63])return r;//如果r是全1数,则直接返回r
	if(a[0]<b[0])return (1ll<<b[0]-1)-1;//如果l的位数比r低,那么不大于r的最大一个"全1数"就是答案。
	//从高位向低位做贪心,相同的话肯定选。停留在p位,有a[p]=0,b[p]=1
	LL ans=0;int p;for(p=a[0];a[p]==b[p];--p)ans+=((LL)a[p]<<p-1);
	//如果r的[1~p-1]存在一位为0,答案就是这一位取0,且之后的位都取1
	for(int j=p-1;j>=1;--j)if(b[j]!=1)return ans+(1ll<<p-1)-1;
	//如果r的[1~p-1]位全是1,答案就是r
	return r;
}
int main()
{
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=n;++i)
		{
			scanf("%lld%lld",&l,&r);
			printf("%lld\n",solve());
		}
	}
	return 0;
}
/*
【trick&&吐槽】
这场比赛,没做好的重要原因就是卡在这题太久>_<
大脑走神,审题不清是重要原因!
做题太急,思维混乱是第二重要原因!

【题意】
给你一个区间[l,r],有0<=l<=r<=1e18
让你求出这个区间范围内二进制表示中,1的个数尽可能多的数中最小的那个

【类型】
讨论

【分析】
这题是讨论题,一定要静下心去呀!
首先,既然是针对一个区间的询问,那么区间的左右边界可是我们研究的重点。
我们可以对左右边界做二进制拆分。

1,如果左右边界拆分出的二进制数的位数不同,那么答案显然是不比r大的最大一个"全1数"
	所谓"全1数",就是这个数的各个位置上的数都是1。

2,如果左右边界拆分出的二进制数的位数相同。我们需要结合数位DP的思想——
	从前向后扫描,前面那部分是相同的,我们没法改变,不要管。
	然后开始到不同的部分了(如果没有,直接输出答案啦)——
	对于第一位,显然的是,这一位,l是0,r是1。
	这说明什么呢?说明l可以取0111……111,就是这个0后面全是1
	只有一种情况这一位会强行取1,就是r=1111……111。

于是这道题就这么讨论完啦!
*/


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值