C2. Sheikh (Hard Version)(貪心&雙指針&bit)
需要注意到 ,因為是不進位加法,是以 ,也就是說這個內插補點是非負的,會随區間長度增加非遞減。是以我們考慮最開始答案設為。因為要求長度最小,是以考慮删除部分字首和字尾使得答案不變的同時,長度變小。
#include<bits/stdc++.h>
using namespace std;
#define N 100002
int T,n,q,a[N],xorh[N],nx[N],pr[N];
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&q);
for(int i=1;i<=n;++i)scanf("%d",a+i),xorh[i]=xorh[i-1]^a[i];
pr[0]=0;
for(int i=1;i<=n;++i)pr[i]=a[i-1]?i-1:pr[i-1];
nx[n]=n+1;
for(int i=n-1;i>=1;--i)nx[i]=a[i+1]?i+1:nx[i+1];
while(q--){
int l,r,xr,ansl,ansr;scanf("%d%d",&l,&r);xr=xorh[r]^xorh[l-1];ansl=l;ansr=r;
for(int ll=l;ll<=r;ll=nx[ll]){
int rr=r;int tmp=xr;
while(ll<=pr[rr]&&(xr|a[rr])==xr)xr^=a[rr],rr=pr[rr];
if((xr|a[rr])==xr)rr=ll;
if(ansr-ansl+1>rr-ll+1){
ansr=rr;ansl=ll;
}
xr=tmp;if((xr|a[ll])!=xr)break;
xr^=a[ll];
}
printf("%d %d\n",ansl,ansr);
}
}
return 0;
}