题目大意
定义函数
f
(
b
1
,
b
2
,
⋯
,
b
m
)
=
{
b
1
m
=
1
f
(
b
1
⨁
b
2
⨁
⋯
⨁
b
m
)
m
>
1
f(b_1,b_2,\cdots,b_m)=\left\{\begin{aligned}b_1 && m = 1 \\ f(b_1\bigoplus b_2 \bigoplus\cdots\bigoplus b_m) && m>1\\ \end{aligned} \right.
f(b1,b2,⋯,bm)=⎩⎨⎧b1f(b1⨁b2⨁⋯⨁bm)m=1m>1
给出一个长度为
n
n
n的数组
a
1
,
a
2
,
⋯
,
a
n
a_1,a_2,\cdots,a_n
a1,a2,⋯,an
并给出
q
q
q个询问,
每次询问给出一个区间
[
l
,
r
]
[l,r]
[l,r],求字数列
a
l
,
a
l
+
1
,
⋯
,
a
r
a_l,a_{l+1},\cdots,a_r
al,al+1,⋯,ar中,最大的
f
f
f是多少。
时间限制
2s
数据范围
n
≤
5000
n\le 5000
n≤5000
q
≤
1
0
5
q\le 10^5
q≤105
题解
这题的关键就是如何快速求出
f
f
f,
比较手推了一下
m
=
1
,
m
=
2
,
m
=
3
,
m
=
4
,
m
=
5
m=1,m=2,m=3,m=4,m=5
m=1,m=2,m=3,m=4,m=5并没有发现任何规律,
不过再次细致地一步一步推到,很快就找到了
f
f
f的递推方法。
不妨设
f
i
,
j
f_{i,j}
fi,j表示
f
(
a
i
,
a
i
+
1
,
⋯
,
a
j
)
f\pod{a_i,a_{i+1},\cdots,a_{j}}
f(ai,ai+1,⋯,aj)
则
f
i
,
j
=
f
i
,
j
−
1
⨁
f
i
+
1
,
j
f_{i,j}=f_{i,j-1}\bigoplus f_{i+1 ,j}
fi,j=fi,j−1⨁fi+1,j
求区间最大值就非常简单了。
Code
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <vector>
#include <queue>
#define G getchar
#define ll long long
using namespace std;
ll read()
{
char ch;
for(ch = G();(ch < '0' || ch > '9') && ch != '-';ch = G());
ll n = 0 , w;
if (ch == '-')
{
w = -1;
ch = G();
} else w = 1;
for(;'0' <= ch && ch <= '9';ch = G())n = (n<<1)+(n<<3)+ch-48;
return n * w;
}
const int N = 5003;
int n , m , f[N][N] , a[N] , s[N];
int z[25] , x , y;
int b[N] , g[N];
int main()
{
//freopen("i.in","r",stdin);
//freopen("2.txt","w",stdout);
z[0] = 1;
for (int i = 1 ; i < 25 ; i++)
z[i] = z[i - 1] * 2;
n = read();
for (int i = 1 ; i <= n ; i++)
{
a[i] = read();
s[i] = s[i - 1] ^ a[i];
f[i][i] = a[i];
}
for (int i = 1 ; i < n ; i++)
for (int j = 1 ; j + i <= n ; j++)
f[j][j + i] = f[j][j + i - 1] ^ f[j + 1][j + i];
for (int i = 1 ; i <= n ; i++)
for (int j = i - 1 ; j ; j--)
{
f[j][i] = max(f[j][i] , f[j][i - 1]);
f[j][i] = max(f[j][i] , f[j + 1][i]);
}
m = read();
for (int i = 0 ; i < m ; i++)
{
x = read();
y = read();
printf("%d\n", f[x][y]);
}
return 0;
}