b b ,定义..." />
当前位置: 代码迷 >> 综合 >> 【CodeForces】【DP】938B XOR-pyramid
  详细解决方案

【CodeForces】【DP】938B XOR-pyramid

热度:73   发布时间:2023-11-21 07:11:36.0

CodeForces 938B XOR-pyramid

题外话

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

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

题目

◇题目传送门◆

题目大意

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

f(b)={ b[1]f(b[1]?b[2],b[2]?b[3],?,b[m?1]?b[m])m=1m>1f(b)={b[1]m=1f(b[1]?b[2],b[2]?b[3],?,b[m?1]?b[m])m>1

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

思路

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

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

举个例子吧:(根据样例一绘制)
这里写图片描述
不难发现, f [ l ] [ r ] 被递归成了f[l+1][r]?f[l][r?1]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][r?1])l=rlrg[l][r]={f[l][r]l=rmax(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 LOACLfreopen("in.txt","r",stdin);freopen("out.txt","w",stdout);#endifscanf("%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;
}
  相关解决方案