(有任何问题欢迎留言或私聊
(这题和异或和半毛钱关系都没有,也别被题面吓走了)
题目:
题意:
给你一段长度为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];
也就是:F[i][j] = F[i][j-1]^F[i+1][j];
到这里题目就解决一半了,剩下的就是用一个dp数组维护i到j的最大F值;
状态转移方程:
F[i][j] = F[i][j-1]^F[i+1][j];
状态转移方程:
dp[i][j] = max( F[i][j], dp[i][j-1], dp[i+1][j] );
初始化:
dp[i][i]=F[i][i]=ar[i];
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5000+7;
int n,q;
int ar[N];
int dp[N][N],f[N][N];
/*
f[i][j]=f[i][j-1]^f[i+1][j];
dp[i][j]=max(f[i][j],dp[i+1][j],dp[i][j-1]);
*/
int main(){
while(~scanf("%d",&n)){
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
for(int i=1;i<=n;++i){
scanf("%d",&ar[i]);//初始化
f[i][i]=dp[i][i]=ar[i];
}
for(int j=2;j<=n;++j){
for(int i=j-1;i>=1;--i){
f[i][j]=f[i+1][j]^f[i][j-1];//计算F值
dp[i][j]=max(f[i][j],max(dp[i][j-1],dp[i+1][j]));//维护区间最大值
}
}
scanf("%d",&q);
while(q--){
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",dp[a][b]);
}
}
return 0;
}