题意:(题意图解转自:点击打开链接)
给你一段长度为n序列,有q次询问;每次询问区间[L,R]内最大的f(x)是多少?
f(x)的含义:F(x)表示x个数在规定运算下的值;
当x=1时,F( 1 ) = a[1];f(1)表示只有一个数,此时f(x)就等于那个值;
当x>1时,F( x ) = F( b[1]^b[2], b[2]^b[3] … b[x-1]^b[x] ); 表示 x 个数的f值;
题目给了组解释:
F(1,2,4,8)=F(1⊕2,2⊕4,4⊕8)=F(3,6,12)=F(3⊕6,6⊕12)=F(5,10)=F(5⊕10)=F(15)=15
画个图理解一下:
此区间有5个数,用F[1][5]表示,从图中最后一步可以得出规律:
F[1][5]=F[1][4]^F[2][5];
剩下的就是一个区间dp了, 枚举长度,枚举起点,只不过这个不必枚举k了, 因为最后的转移式已经知道了
#include <iostream>
#include <cstring>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
const int maxn = 5e3 + 5;
int f[maxn][maxn], dp[maxn][maxn], a[maxn];
int main()
{
int n, q;
while(~scanf("%d", &n))
{
memset(dp, 0, sizeof(dp));
memset(f, 0, sizeof(f));
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]), f[i][i] = a[i], dp[i][i] = a[i];
for(int len = 1; len <= n; len++)
{
for(int l = 1; l+len <= n; l++)
{
int r = l + len;
f[l][r] = f[l+1][r] ^ f[l][r-1];
dp[l][r] = max(f[l][r], max(dp[l+1][r], dp[l][r-1]));
}
}
int q;
cin >> q;
while(q--)
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", dp[l][r]);
}
}
return 0;
}