D - Birthday Gift
题目大意:
思路解析:
题目要求我们尽可能将数组分成多个段,使得每个段的异或值的 或小于等于x。
(1)那我们想 如果 x = (xxxx1001010) (2进制表示)
如果我们分成k个段后能使得 cur = (xxxx0xxxxxx) (2进制表示)如果我们能使得在某位x为1,并且答案当前位为0,那么后面的值无论是什么,都能满足或和小于等于x。那这种情况下的最优是什么呢,我们假设 a[i] 和 a[j]在当前位为1,那我们便组成一个区间[i,j],这样的区间一定不能划分,但是剩余数,因为无论组成什么都能满足答案,所以让这些数,组成一个单独的区间。 (这里直接统计当前状态的答案,然后在后面低位的枚举时,默认这里填充的1)
如果我们分成k个段后不能使得 cur = (xxxx0xxxxxx) (2进制表示)如果我们不能使得在某位x为1,那么这位就没有对答案没有影响
(2)如果 x = (xxxxx01000) (2进制表示)
如果x当前位为0, 如果我们不能使得分成k段后,当前位为0,那么无论后面怎么分都是无效解。
如果能使得当前位为0, 假设有某些数a[i] 和 a[j] 在当前位为1,那我们让他组成区间[i,j] 并且这个区间在以后也一定不能分开了。
这样就可以对每种情况的答案进行统计。
代码实现:
import java.io.*;
import java.math.BigInteger;
import java.util.*;
public class Main {
static int inf = (int) 2e7;
public static void main(String[] args) throws IOException {
int t = f.nextInt();
while (t > 0) {
solve();
t--;
}
w.flush();
w.close();
br.close();
}
static int maxN = 100005;
public static void solve() {
int ans = -1;
int n = f.nextInt(); int m = f.nextInt();
int[] a = new int[n+1]; boolean[] flag = new boolean[n+1];
for (int i = 1; i <= n; i++) {
a[i] = f.nextInt(); flag[i] = true;
}
for (int i = 29; i >= 0; i--) {
boolean ok = true;
int cnt = 0;
if (((m >> i) & 1) != 0){
for (int j = 1; j <= n; j++) {
if (((a[j] >> i) & 1) != 0) ok = !ok;
if (ok && flag[j]) cnt++;
}
if(ok) ans = Math.max(ans, cnt);
}else {
for (int j = 1; j <= n; j++) {
if (((a[j] >> i) & 1) != 0) ok = !ok;
if (!ok) flag[j] = false;
}
if (!ok) {w.println(ans); return;}
}
}
int temp = 0;
for (int i = 1; i <= n; i++) {
if (flag[i]) temp++;
}
ans = Math.max(ans, temp);
w.println(ans);
}
static PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out));
static Input f = new Input(System.in);
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static class Input {
public BufferedReader reader;
public StringTokenizer tokenizer;
public Input(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
}
}