(有任何问题欢迎留言或私聊
(这题和异或和半毛钱关系都没有,也别被题面吓走了)
题目:
题意:
给你一段长度为 n n 序列,有次询问;每次询问区间 [L,R] [ L , R ] 内最大的 f(x) f ( x ) 是多少?
f(x) f ( x ) 的含义: F(x) F ( x ) 表示 x x 个数在规定运算下的值;
当时, F(1)=a[1]; F ( 1 ) = a [ 1 ] ; f(1)表示只有一个数,此时 f(x) f ( x ) 就等于那个值;
当 x>1 x > 1 时, F(x)=F(b[1] F ( x ) = F ( b [ 1 ] ^ b[2],b[2] b [ 2 ] , b [ 2 ] ^ b[3]...b[x−1] b [ 3 ] . . . b [ x − 1 ] ^ b[x]); b [ x ] ) ; 表示 x x 个数的f值;
题目给了组解释:
画个图理解一下:
此区间有5个数,用F[1][5]表示,从图中最后一步可以得出规律:
F[1][5]=F[1][4]
F
[
1
]
[
5
]
=
F
[
1
]
[
4
]
^
F[2][5]
F
[
2
]
[
5
]
也就是:
F[i][j]=F[i][j−1]
F
[
i
]
[
j
]
=
F
[
i
]
[
j
−
1
]
^
F[i+1][j]
F
[
i
+
1
]
[
j
]
到这里题目就解决一半了,剩下的就是用一个dp数组维护i到j的最大F值;
状态转移方程:
F[i][j]=F[i][j−1] F [ i ] [ j ] = F [ i ] [ j − 1 ] ^ F[i+1][j]; F [ i + 1 ] [ j ] ;
状态转移方程:
dp[i][j]=max(F[i][j],dp[i][j−1],dp[i+1][j]); d p [ i ] [ j ] = m a x ( F [ i ] [ j ] , d p [ i ] [ j − 1 ] , d p [ i + 1 ] [ j ] ) ;
初始化:
dp[i][i]=F[i][i]=ar[i]; d p [ i ] [ i ] = F [ i ] [ i ] = a r [ 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;
}