题解:P14359 [CSP-J 2025] 异或和 / xor(民间数据)

· · 题解

水一下 CSP-J 2025 的题解。

思路:

设前缀异或 p_i=a_1\oplus\cdots\oplus a_i,则区间 [l,r] 的异或和为 k 当且仅当 p_{l-1}=p_r\oplus k。设 dp_i 为前 i 个元素内能选的不相交区间最多个数。若区间以 i 结尾,则它的左端点前一个位置是某个 j 满足 p_j=p_i\oplus k,贡献为 d_j+1。因此只需维护每个前缀异或值 v 的“目前最优 dp”。

其中,“目前最优 dp”指的是:对每个前缀异或值 v,在当前下标之前出现过的所有位置 j 里,dp_j 的最大值。

故转移为

先用 $best$ 计算,再更新 $best$,可避免把当前下标当作左端的“空区间”,确保不重叠。 * 初始:$p_0=0$,$dp_0=0$,故令 $best[0]=0$,其余置为 $-\infty$。 * 取值范围 $a_i,k<2^{20}$,故数组 $best$ 大小取 $2^{20}$ 即可。时间复杂度 $\mathcal O(n+2^{20})$,空间复杂度 $\mathcal O(2^{20})$。足以通过本题。 代码: ```cpp #include<bits/stdc++.h> using namespace std; const int maxn=1<<20; int best[maxn]; int main(){ int n,k; cin>>n>>k; for(int i=1;i<=maxn;i++) best[i]=-1e9; best[0]=0; int x=0,dp=0; for(int i=1,a;i<=n;i++){ cin>>a; x^=a; int t=best[x^k]; int nd=dp; if(t>-1e9) nd=max(nd,t+1); dp=nd; if(best[x]<dp) best[x]=dp; } cout<<dp; return 0; } ```