CodeForces - 484A(位运算)

  • 题目传送门:~~~

题目大意

有 t 次查询,每次查询(l, r)区间中,二进制下 1 的个数出现最多的数,如果有多个答案,输出最小的那个

分析

我们只需要在 l 上补 1 就可以了。具体操作:

  • step1:令结果res = l,再定义一个指针 ind = 1。
  • step2:我们比较 res | ind 和 r 的关系,如果 (res | ind) <= r ,我们就更新 res = res | ind,| 运算可以把 ind 二进制下的 1 给加到 res 上。 如果 (res | ind) > r ,当前res就是答案
  • step3:我们让 ind 右移一位,再回到 step2

我们拿一个样例看看
R = 1011 01012
L = 1010 00102
令 res = 1010 00102,ind = 0000 00012


  • 第一次执行step2
    (res | ind) = 1010 00112 < 1011 01012
    更新 res = res = res | ind = 1011 00112
    更新 ind = 0000 00102

  • 第二次执行step2
    (res | ind) = 1010 00112 < 1011 01012
    更新 res = res = res | ind = 1011 00112
    更新 ind = 0000 01002

  • 第三次执行step2
    (res | ind) = 1010 01112 < 1011 01012
    更新 res = res = res | ind = 1010 01112
    更新 ind = 0000 10002

  • 第四次执行step2
    (res | ind) = 1010 11112 < 1011 01012
    更新 res = res = res | ind = 1011 11112
    更新 ind = 0001 00002

  • 第五次次执行step2
    (res | ind) = 1011 11112 > 1011 01012
    结束

通过上边的过程我们可以看出,在给 l 不断补 1 过程中,我找到了答案
这个题的解决方法有很多,最突出的问题就是解决输出最小的答案。我们通过右到左的扫描二进制下的 r 和 l 实现最小答案

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;

int main(){
	
	int ncase;
	cin >> ncase;
	while(ncase--){
		ll l, r;
		cin >> l >> r;
		for(ll i = 1; (l | i) <= r; i <<= 1) l |= i;     // 补一的过程
		cout << l << endl;
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/mldl_/article/details/106136291