Codeforces Round #832 (Div. 2) D (预处理+二分)
D. Yet Another Problem
观察题干 发现一定要是odd
考虑发掘性质 发现之后还会将[l,r]长度为奇数的区间全部赋值成这个区间的异或和
我们设长度为len len-1个偶数个异或为0 最后一个异或剩下来还是总体的异或和
也就是我们进行了一次操作后异或和是不变的
我们考虑用这个性质
对于查询[l,r]要是区间异或和不为0 因为无论如何 我们异或和是不变的 所以肯定不可能变成0
我们继续思考
要是查询长度是奇数 我们可以通过一次全部直接完成
要是查询的全部都是0 我们可以直接输出0 这个可以通过处理前缀和完成 因为我们都是正数所以sum[l-1]sum[r] 就是这个区间都是0
要是查询长度为偶数 我们要是左右两边有一个0 那我们这个就可以看作一个0+一个奇数长度 就是1
要是两边没有0 我们知道我们区间异或和=0 也就是s[l-1]^s[r]0 等价于 s[l-1]s[r] 且l,r的奇偶性相同
所以我们只用查询区间内是否还有一个点与l,r寄偶性不同 并且 s[x]s[l-r]==s[r]这样我们就可以通过两次操作把整个区间变为0了
最后注意我们的s[x]值域很大 我们要离散化 还有寄偶性不同的要分别放进不同的map方便查询 最后用指针比较方便判断end()
void solve(){ int n,q;cin>>n>>q; vector<int>a(n+10),s(n+10),sum(n+10); map<int,vector<int>>v1,v; for(int i=1;i<=n;i++){ cin>>a[i]; s[i]=a[i]; s[i]^=s[i-1]; sum[i]=a[i]+sum[i-1]; if(i&1)v1[s[i]].push_back(i); else v[s[i]].push_back(i); } while(q--){ int l,r;cin>>l>>r; int len=r-l+1; if(s[l-1]^s[r]){ cout<<-1<<endl; continue; } if(sum[l-1]==sum[r]){ cout<<0<<endl; continue; } if(len&1){ cout<<1<<endl; }else{ if(a[l]==0||a[r]==0){ cout<<1<<endl; }else{ if((l-1)&1){ auto it=lower_bound(all(v[s[l-1]]),l-1); if(it!=v[s[l-1]].end()&&*it<r){ cout<<2<<endl; continue; } }else{ auto it= lower_bound(all(v1[s[l-1]]),l-1); if(it!=v1[s[l-1]].end()&&*it<r){ cout<<2<<endl; continue; } } cout<<-1<<endl; } } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】