Codeforce984D-XOR-pyramid-找规律DP

(有任何问题欢迎留言或私聊

(这题和异或和半毛钱关系都没有,也别被题面吓走了)

题目:

这里写图片描述

题意:

 给你一段长度为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;
}

猜你喜欢

转载自blog.csdn.net/qq_39599067/article/details/80335949
今日推荐