这又是一道神奇的题,(我居然忘记了异或运算的神奇的性质),意思就是给你一个序列,然后让你找到一个区间内最小的区间,让我们的 (和 减去 异或 的值)res 最大,也就是这个东西
f(l,r)=sum(l,r)−xor(l,r)f(l,r)=sum(l,r)−xor(l,r),我们可以这样去理解这个东西,用一些数的进位加法减去这些数的不进位加法,想一下这个过程,他是递增的操作,所以询问区间的 res应该是一个定值,所以我们只需要二分答案区间的长度并且判断一下即可。
以下是ac代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N =2e5 + 10;
typedef long long int LL ;
LL a[N];
LL b[N];
LL c[N];
LL find(int le , int re)
{
return b[re] - b[le-1] - (c[re] ^ c[le-1]);
}
LL ans;//求的当前区间的答案。
LL len;//求得当前区间的长度
LL xiabiao;//求得当前区间的起始下标。
int n ,m;
int L , R;//查询区间。
bool check(int mid)
{
LL maxd = -1;
LL pee = 0 ;
int le, re;
for(int i = L ; i + mid - 1 <= R ; i ++)
{
le = i ,re = i + mid - 1;
LL temp = find(le,re);
if(maxd < temp)
{
pee = i ;
maxd = temp;
}
// cout << le <<' '<< re <<' '<< find(le,re)<<' '<< temp <<endl;
}
if(maxd == ans && mid < len)
{
len = mid ;
xiabiao = pee;
}
if(maxd == ans)return true;
return false;
}
int main()
{
int t;
cin >> t;
while(t--)
{
cin >> n >> m ;
for(int i = 1; i <= n ; i ++)
{
cin >> a[i];
b[i] = b[i-1] + a[i];
c[i] = c[i-1] ^ a[i];
}
cin >> L >> R ;
ans = find(L,R);
len = R - L + 1;
xiabiao = L ;
int l = 1, r = len;
// cout << ans <<' '<<find(1,12)<<endl;
// cout << find(1,13)<<endl;
// cout << check(13)<<endl;
while(l < r)
{
int mid = l + r >> 1;
if(check(mid))r = mid;
else l = mid + 1;
}
cout << xiabiao <<' '<<xiabiao + len - 1 << endl;
}
}