题意:
对一个序列b,定义一种运算
f(b)={b[1]f(b[1]⊕b[2],b[2]⊕b[3],…,b[m−1]⊕b[m])if m=1otherwise,
f
(
b
)
=
{
b
[
1
]
if
m
=
1
f
(
b
[
1
]
⊕
b
[
2
]
,
b
[
2
]
⊕
b
[
3
]
,
…
,
b
[
m
−
1
]
⊕
b
[
m
]
)
otherwise,
(
⊕
⊕
表示异或)
现在给出一个长为N的序列b,以及q次询问,每次询问给出
l,r
l
,
r
表示从l到r这段子序列中,最大的f(b’)的值
N≤5000,q≤100000
N
≤
5000
,
q
≤
100000
分析:
设
d(i,j)
d
(
i
,
j
)
表示
f({ai,ai+1,……,aj})
f
(
{
a
i
,
a
i
+
1
,
…
…
,
a
j
}
)
根据异或的自反性,很容易发现,
d(i,j)=d(i+1,j)⊕d(i,j−1)
d
(
i
,
j
)
=
d
(
i
+
1
,
j
)
⊕
d
(
i
,
j
−
1
)
根据这个性质,我们就可以在
O(n2)
O
(
n
2
)
复杂度内,得到所有子序列的f(b’)
然后再随便搞个
O(n2)
O
(
n
2
)
的dp统计区间最大值即可。
dp(i,j)=max{d(i,j),dp(i+1,j),dp(i,j−1)}
d
p
(
i
,
j
)
=
m
a
x
{
d
(
i
,
j
)
,
d
p
(
i
+
1
,
j
)
,
d
p
(
i
,
j
−
1
)
}
每次询问直接输出答案即可。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 5010
using namespace std;
typedef long long ll;
int n;
ll a[MAXN];
ll dp[MAXN][MAXN],ans[MAXN][MAXN];
int main(){
SF("%d",&n);
for(int i=1;i<=n;i++){
SF("%I64d",&a[i]);
dp[i][i]=a[i];
ans[i][i]=a[i];
}
for(int i=1;i<=n;i++)
for(int j=1;j+i<=n;j++){
dp[j][i+j]=dp[j][i+j-1]^dp[j+1][i+j];
ans[j][i+j]=dp[j][i+j];
}
for(int i=1;i<=n;i++)
for(int j=1;j+i<=n;j++){
ans[j][i+j]=max(ans[j][i+j],max(ans[j+1][i+j],ans[j][i+j-1]));
}
int q,l,r;
SF("%d",&q);
for(int i=1;i<=q;i++){
SF("%d%d",&l,&r);
PF("%I64d\n",ans[l][r]);
}
}