此题的题意大致是说,给出一个数组,并定义一个运算f(b),这个运算在参数个数大于1时递归地计算相邻参数两两异或的结果,每次迭代都会减少一个参数。题目要求求解这串数组中任意一个片段通过f(b)运算获得的最大结果。
由此看出,异或在此题中只是作为一个运算符使用的,不需要我们去理解。那么这题就被转化为类似与数塔问题的基础DP问题。但要注意的一点是,数塔问题是对于整个数组求最优解,此题要求的是“任一片段的最优解”,因此在自底向上做完状态转移后,还需遍历一遍得到的二维数组,将dp[i][j]更新为dp[i][j],dp[i-1][j],dp[i-1][j+1]中的最大值(因为DP的最优子结构性质,dp数组中的每个元素都代表了当前片段的最优解,因此只用将整个数组的最优解继承到顶部即可)。
AC代码如下:
#include<iostream>
#include<set>
#include<utility>
#include<map>
#include<algorithm>
#include<queue>
#include<cstring>
#include<string>
#include<vector>
#include<cstdio>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
long long dp[5050][5050],a[5050];
long long maxx(long long a,long long b,long long c){
return a>max(b,c)?a:max(b,c);
}
int main() {
long long n;
while(cin>>n){
memset(dp,0,sizeof(dp));
memset(a,0,sizeof(a));
long long q;
for(int i=0;i<n;i++){
cin>>a[i];
dp[0][i]=a[i];
}
for(int i=1;i<n;i++){
for(int j=0;j<n-i;j++){
dp[i][j]=dp[i-1][j]^dp[i-1][j+1];
}
}
for(int i=1;i<n;i++){
for(int j=0;j<n-i;j++){
dp[i][j]=maxx(dp[i][j],dp[i-1][j],dp[i-1][j+1]);
}
}
// for(int i=0;i<n;i++){
// cout<<"*";
// for(int j=0;j<n-i;j++){
// printf("%2d ",dp[i][j]); 这一段代码用于输出整个数组,方便调试
// }
// cout<<endl;
// }
long long l,r;
cin>>q;
for(int i=0;i<q;i++){
cin>>l>>r;
cout<<dp[r-l][l-1]<<endl;
}
}
return 0;
}
需要注意的是,若使用自底向上方法,最后取用数组中元素的时候,需要对下标做一下变化,这里可以在草稿纸上先写出结果再做分析,也可以直接先输出整个DP数组,用来分析。