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;
}
}
}
}
标签:832,int,sum,Codeforces,Round,异或,区间,查询,我们
From: https://www.cnblogs.com/ycllz/p/16863051.html