CF1747D
题意
给定一个长度为
思路
考虑这样一个性质:每次操作后不会改变这个区间的异或值。
证明:设当前操作的区间为
。设 ,操作后序列变为 个 连接而成,由于 ,所以 ,即操作后区间异或值不改变。
根据这个性质开始分类讨论。
如果询问区间每个数初始时均为
如果一个区间的异或值不为
如果询问区间长度为奇数,对整个区间操作
最后剩下区间长度为偶数的情况。发现并不是所有的情况都有解,比如
所以,当询问区间长为偶数时,当且经当这个区间存在一个长为奇数的异或和为
考虑如何快速判断是否存在长为奇数的前缀异或和为
但我赛时以为偶数情况有解时一定要操作两次,导致WA on test2了无数发。其实有些情况只需要操作一次。比如
Code
点击查看代码
#include <bits/stdc++.h> using namespace std; #define ll long long const ll SIZE = 200005; const ll mod = 998244353; ll n, T; ll a[SIZE], sum[SIZE]; ll cnt[SIZE]; ll nx[SIZE]; map<ll, ll> mp[2]; inline ll rd(){ ll f = 1, x = 0; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } return f*x; } int main(){ n = rd(); T = rd(); for(ll i = 1; i <= n; i++) { a[i] = rd(), sum[i] = (sum[i-1] ^ a[i]); cnt[i] = cnt[i-1] + a[i]; } for(ll i = n; i >= 0; i--){ nx[i] = mp[(i%2)^1][sum[i]]; if(nx[i] == 0) nx[i] = n+1; mp[i%2][sum[i]] = i; } while(T--){ ll l = rd(), r = rd(); if(sum[r] ^ sum[l-1]) printf("-1\n"); else if(cnt[r] - cnt[l-1] == 0) printf("0\n"); else if((r-l+1)&1) printf("1\n"); else if(nx[l-1] <= r){ if(a[l] == 0 || a[r] == 0) printf("1\n"); else printf("2\n"); } else printf("-1\n"); } return 0; }
本文作者:Semorius
本文链接:https://www.cnblogs.com/Semorius/p/17538289.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步