【CodeForces】【DP】938B XOR-pyramid

6 篇文章 0 订阅
5 篇文章 0 订阅

CodeForces 938B XOR-pyramid

题外话

当我考试时看到这道题时,离考试结束只剩20分钟了。。。

然后,我飞一般地分析了样例,猜出了结论,过了这道题。(想想都觉得惊心动魄。。。手都要起飞了。。。)

题目

◇题目传送门◆

题目大意

对于一个长度为 m m 的数组b,定义函数:

f(b)={b[1]f(b[1]b[2],b[2]b[3],,b[m1]b[m])m=1m>1 f ( b ) = { b [ 1 ] m = 1 f ( b [ 1 ] ⨁ b [ 2 ] , b [ 2 ] ⨁ b [ 3 ] , ⋯ , b [ m − 1 ] ⨁ b [ m ] ) m > 1

现给定一个长度为 n n 序列a,给出 q q 个询问,对于每个询问,输出给定区间内连续子串的最大函数值。

思路

看题可知,q的值非常地大( q100000 q ≤ 100000 )而 n n 却非常小(n5000),很容易往离线操作上靠,即用 O(1) O ( 1 ) 的时间复杂度来回答询问。DP是一个不错的选择。

我们定义 f[l][r] f [ l ] [ r ] 为区间 [l,r] [ l , r ] f f 函数值。先来找一下规律:

举个例子吧:(根据样例一绘制)
这里写图片描述
不难发现,f[l][r]被递归成了 f[l+1][r]f[l][r1] f [ l + 1 ] [ r ] ⨁ f [ l ] [ r − 1 ] 。(画图分析是多么重要)

我们还可以发现边界条件: f[l][r]=a[l](l=r) f [ l ] [ r ] = a [ l ] ( l = r )

若实在不相信这个结论,就请画出更多的图,你会发现这个结论是正确的。

自然,这道题就变成了一道区间DP题。

我们再定义 g[l][r] g [ l ] [ r ] 为区间 [l,r] [ l , r ] 的最大函数值,可得出状态转移方程:

g[l][r]={f[l][r]max(f[l][r],g[l+1][r],g[l][r1])l=rlr g [ l ] [ r ] = { f [ l ] [ r ] l = r max ( f [ l ] [ r ] , g [ l + 1 ] [ r ] , g [ l ] [ r − 1 ] ) l ≠ r

所以,还等什么呢?

正解代码

#include<cstdio>
#include<algorithm>
using namespace std;

const int Maxn=5000;

int N,A[Maxn+5];
int f[Maxn+5][Maxn+5];
int ans[Maxn+5][Maxn+5];

int main() {
    #ifdef LOACL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
    scanf("%d",&N);
    for(int i=1;i<=N;i++) {
        scanf("%d",&A[i]);
        ans[i][i]=f[i][i]=A[i];
    }
    for(int i=2;i<=N;i++)
        for(int j=1;j<=N-i+1;j++) {
            int k=j+i-1;
            f[j][k]=f[j+1][k]^f[j][k-1];
            ans[j][k]=max(ans[j+1][k],ans[j][k-1]);
            if(f[j][k]>ans[j][k])ans[j][k]=f[j][k];
        }
    int q;
    scanf("%d",&q);
    while(q--) {
        int l,r;
        scanf("%d %d",&l,&r);
        printf("%d\n",ans[l][r]);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值