题意:给定你一个数组,给定m个查询Li,Ri,要求找到每个查询区间中a[l]+a[l+1]+...+a[r]-a[l]^a[l+1]^...a[r]最大值的长度最小的区间的左右下标
思路:暴力的做法是枚举左端点,利用右端点在右半部分是单调的特性二分从而找到最小的区间。但是这样做会导致hard版本tle。
于是我们想到探究这个式子的特性:左右两边可删去的非零数字是有限的,且这个数的数量级比较小,我们想到,左右两边如果总共删除超过60个数就会必定导致结果改变(具体的讲,是会变小)。于是我们维护非零数字的数量,以及它们之间的相对位置关系,再进行暴力枚举,就可以得出答案了
至于为什么是60个数,原因在于每一位上最多重复删两次(ps:实际上31个数就足够了,因为我们只需要有一位上有重复,但是防止边界问题,就留足余量啦)。
注意左右都必须是60,才能覆盖所有情况
注意特殊情况等于0时的特判(此时能删除所有数只保留一个就行了)
注意记录相对关系时的边界条件特判
EAZY版的做法(实际上hard版与eazy版之间hard是可以套在eazy上的)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<bitset>
#include<cmath>
#include<array>
#include<atomic>
#include<sstream>
#include<stack>
#include<iomanip>
//#include<bits/stdc++.h>
//#define int ll
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0);
#define pb push_back
#define endl '\n'
#define x first
#define y second
#define Endl endl
#define pre(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,b,a) for(int i=b;i>=a;i--)
#define si(x) scanf("%d", &x);
#define sl(x) scanf("%lld", &x);
#define ss(x) scanf("%s", x);
#define YES {puts("YES");return;}
#define NO {puts("NO"); return;}
#define all(x) x.begin(),x.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<int, PII> PIII;
typedef pair<char, int> PCI;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<ll, ll> PLL;
const int N = 500010, M = 2 * N, B = N, MOD = 998244353;
const double eps = 1e-7;
const int INF = 0x3f3f3f3f;
const ll LLINF = 0x3f3f3f3f3f3f3f3f;
//int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 };
int dx[8] = { 1,2,2,1,-1,-2,-2,-1 }, dy[8] = { 2,1,-1,-2,-2,-1,1,2 };
int n, m, k;
int a[N];
ll sum[N];
int pxor[N];
int bkidx[55], ftidx[55];
int heap[N][55];
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lowbit(ll x) { return x & -x; }
ll qmi(ll a, ll b, ll MOD) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
inline void init() {}
ll f(int l, int r)
{
return sum[r] - sum[l - 1] - (pxor[r] ^ pxor[l-1]);
}
bool check(int l,int r,ll c)
{
return f(l, r) == c;
}
void slove()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];
for (int i = 1; i <= n; i++) pxor[i] = pxor[i - 1] ^ a[i];
while (m--)
{
int L, R;
cin >> L >> R;
PII ans = { L,R };
ll k = f(L, R);
for (int i = L; i <= R; i++)
{
int l = i, r = R + 1;
while (l < r)
{
int mid = l + r >> 1;
if (check(i, mid, k))r = mid;
else l = mid + 1;
}
if (r == R + 1)continue;
if (r - i < ans.y - ans.x) ans = { i,r };
}
cout << ans.x << ' ' << ans.y << endl;
}
return;
}
signed main()
{
//IOS;
int _ = 1;
si(_);
init();
while (_--)
{
slove();
}
return 0;
}
/*
1
4 1
0 12 8 3
1 4
*/
HARD版
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<string>
#include<bitset>
#include<cmath>
#include<array>
#include<atomic>
#include<sstream>
#include<stack>
#include<iomanip>
//#include<bits/stdc++.h>
//#define int ll
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0);
#define pb push_back
#define endl '\n'
#define x first
#define y second
#define Endl endl
#define pre(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,b,a) for(int i=b;i>=a;i--)
#define si(x) scanf("%d", &x);
#define sl(x) scanf("%lld", &x);
#define ss(x) scanf("%s", x);
#define YES {puts("YES");return;}
#define NO {puts("NO"); return;}
#define all(x) x.begin(),x.end()
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<int, PII> PIII;
typedef pair<char, int> PCI;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<ll, ll> PLL;
const int N = 500010, M = 2 * N, B = N, MOD = 998244353;
const double eps = 1e-7;
const int INF = 0x3f3f3f3f;
const ll LLINF = 0x3f3f3f3f3f3f3f3f;
//int dx[4] = { -1,0,1,0 }, dy[4] = { 0,1,0,-1 };
int dx[8] = { 1,2,2,1,-1,-2,-2,-1 }, dy[8] = { 2,1,-1,-2,-2,-1,1,2 };
int n, m, k;
int a[N];
ll sum[N];
int pxor[N];
int nex[N], pre[N];
int cnt[N];
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lowbit(ll x) { return x & -x; }
ll qmi(ll a, ll b, ll MOD) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return res;
}
inline void init() {}
ll f(int l, int r)
{
return sum[r] - sum[l - 1] - (pxor[r] ^ pxor[l-1]);
}
bool check(int l,int r,ll c)
{
return f(l, r) == c;
}
void slove()
{
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i];
for (int i = 1; i <= n; i++) pxor[i] = pxor[i - 1] ^ a[i];
for (int i = 1; i <= n; i++) cnt[i] = cnt[i - 1] + (a[i] != 0);
nex[n] = INF, pre[1] = -INF;
for (int i = 2; i <= n; i++) {
if (a[i - 1])pre[i] = i - 1;
else pre[i] = pre[i - 1];
}
for (int i = n-1; i >= 1; i--) {
if (a[i + 1])nex[i] = i + 1;
else nex[i] = nex[i + 1];
}
while (m--)
{
int L, R;
cin >> L >> R;
ll k = f(L, R);
PII ans = { L,R };
if (cnt[R] - cnt[L - 1] == 0)ans = { L,L };
else if (cnt[R] - cnt[L] <= 60)
{
if (!a[L]) L = nex[L];
if (!a[R])R = pre[R];
for(int i=L;i<=R;i=nex[i])
for (int j = i; j <= R; j = nex[j])
{
if (f(i, j) == k && j - i < ans.y - ans.x) {
ans = { i,j };
}
}
}
else {
vector<int> le, ri;
if (!a[L]) L = nex[L];
if (!a[R])R = pre[R];
for (int i = L, cnt = 0; i <= R && cnt < 60; i = nex[i], cnt++)
le.push_back(i);
for (int i = R, cnt = 0; i >= L && cnt < 60; i = pre[i], cnt++)
ri.push_back(i);
for(int& i:le)
for (int& j : ri)
{
if (i > j)continue;
if (f(i, j) == k && j - i < ans.y - ans.x) {
ans = { i,j };
}
}
}
cout<< ans.x << ' ' << ans.y << Endl;
}
return;
}
signed main()
{
//IOS;
int _ = 1;
si(_);
init();
while (_--)
{
slove();
}
return 0;
}
/*
1
7 7
0 1 0 1 0 1 0
1 7
3 6
2 5
1 4
4 7
2 6
2 7
*/