CF1604B XOR Specia-LIS-t 题解
考场上想出了近似做法,可惜没有实现出来。
题意
有 \(t\) 组数据,每组都是一个有 \(n\) 个元素的序列 \(a\),考虑将此序列分割成若干段。假设第 \(i\) 段的 LIS(最长上升子序列)长度为 \(h_i\),请问是否有一种分割方式使得 \(h_1 \oplus h_2\oplus\dots\) 的值为 \(0\)?
数据范围 \(1\leqslant t\leqslant10000\),\(2\leqslant n\leqslant10^5\),所有 \(n\) 之和不超过 \(3\cdot 10^5\)。
思路
肯定不能每次暴力分割,所以考虑 LIS 的性质。
- 一个单调不升序列的 LIS 一定是 \(1\)。
- 一个元素的序列的 LIS 一定是 \(1\)。
再很容易想到,一堆 \(1\) 异或起来,答案不是 \(1\) 就是 \(0\)。偶数个 \(1\) 异或,答案就是 \(0\);奇数个 \(1\) 异或,答案是 \(1\),再来一个 \(1\) 答案就能变成 \(0\)。
所以对于 \(n\bmod 2=0\) 的情况一定有解(每个元素单独成一段),而对于 \(n\bmod 2=1\) 的情况,考虑把两个元素合为一段,剩下的元素还是单独成段。若合起来的两个元素刚好构成一个单调不升序列就有解,否则无解。
代码
数学题的好处就是想清楚了代码很精简。
//solve 函数的主体
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
if(n%2==0){//偶数元素一定有解
puts("YES");
return;
}
else{
for(int i=2;i<=n;i++){
if(a[i-1]>=a[i]){//判断是否可以组成单调不升序列
puts("YES");//有两个元素能组成就有解
return;
}
}
puts("NO");//如果组成不了单调不升序列就没有解
return;
}