【Gym - 101608G】WiFi Password (区间或,线段树 或 按位处理+尺取 或 二分)

版权声明:欢迎学习我的博客,希望ACM的发展越来越好~ https://blog.csdn.net/qq_41289920/article/details/89026778

题干:

Just days before the JCPC, your internet service went down. You decided to continue your training at the ACM club at your university. Sadly, you discovered that they have changed the WiFi password. On the router, the following question was mentioned, the answer is the WiFi password padded with zeros as needed.

A subarray [l, r] of an array A is defined as a sequence of consecutive elements Al, Al + 1, ..., Ar, the length of such subarray is r - l + 1. The bitwise OR of the subarray is defined as: Al OR Al + 1 OR ... OR Ar, where OR is the bitwise OR operation (check the notes for details).

Given an array A of n positive integers and an integer v, find the maximum length of a subarray such that the bitwise OR of its elements is less than or equal to v.

Input

The first line contains an integer T (1 ≤ T ≤ 128), where T is the number of test cases.

The first line of each test case contains two space-separated integers n and v (1 ≤ n ≤ 105) (1 ≤ v ≤ 3 × 105).

The second line contains n space-separated integers A1, A2, ..., An (1 ≤ Ai ≤ 2 × 105), the elements of the array.

The sum of n overall test cases does not exceed 106.

Output

For each test case, if no subarray meets the requirement, print 0. Otherwise, print the maximum length of a subarray that meets the requirement.

Example

Input

3
5 8
1 4 5 3 1
5 10
8 2 6 1 10
4 2
9 4 5 8

Output

5
3
0

Note

To get the value of x OR y, consider both numbers in binary (padded with zeros to make their lengths equal), apply the OR operation on the corresponding bits, and return the result into decimal form. For example, the result of 10 OR 17 = 01010 OR 10001 = 11011 = 27.

题目大意:

给你n和m,n代表有n个数,然后让你找出一个最长的区间,使得这个区间内的所有数的‘’或‘’都小于等于m。

解题报告:

   因为或运算对于区间长度是满足单调不减性的,所以我们可以二分长度+check。其实尺取是最优秀的但是二分好写一些,并且告诉你了n的总数量<=1e6,所以二分足够了,这个总复杂度应该是nlognlogn的。

  因为满足区间加和的性质,所以这题也可以线段树去做(反正不带更新,如果带更新就麻烦了⑧),这样还是尺取,然后每次log去查询区间和就好了,抽空写一写。

AC代码:(592ms水过)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 1e5 + 5;
int a[MAX],n,v;
int d[MAX][22];
int cnt[22];
int cal() {
	int res = 0;
	for(int j = 0; j<22; j++) {
		if(cnt[j]>0) res += (1<<j); 
	}
	return res;
}
bool ok(int x) {
	memset(cnt,0,sizeof cnt);
	for(int i = 1; i<=x; i++) {
		for(int j = 0; j<22; j++) cnt[j] += d[i][j];
	}
	int sum = cal();
	if(sum <= v) return 1;
	for(int l = 2; l+x-1<=n; l++) {
		int r = l+x-1;
		for(int j = 0; j<22; j++) cnt[j] -= d[l-1][j];
		for(int j = 0; j<22; j++) cnt[j] += d[r][j];
		if(cal() <= v) return 1;
	}
	return 0 ;
}
int main()
{
	freopen("wifi.in","r",stdin);
	int t;
	cin>>t;
	while(t--) {
		scanf("%d%d",&n,&v);
		memset(d,0,sizeof d);
		for(int i = 1; i<=n; i++) scanf("%d",a+i);
		for(int i = 1; i<=n; i++) {
			int tmp = a[i],cur = 0;
			while(tmp) {
				d[i][cur++] = tmp%2;
				tmp/=2;
			}
		}
		int l = 1,r = n,mid = (l+r)>>1,ans=0;
		while(l<=r) {
			mid=(l+r)>>1;
			if(ok(mid)) ans = mid,l = mid+1;
			else r = mid-1;
		}
		printf("%d\n",ans);
	}
	return 0 ;
}

猜你喜欢

转载自blog.csdn.net/qq_41289920/article/details/89026778