CF 983B XOR-pyramid(区间dp,异或)
若有一个长度为m的数组b,定义函数f为:
$f(b) = \begin{cases} b[1] & \quad \text{if } m = 1, \ f(b[1] \oplus b[2],b[2] \oplus b[3],\dots,b[m-1] \oplus b[m]) & \quad \text{otherwise} \end{cases}$
现在给出长度为n(n<=5000)的数组a,询问q(q<=100000)次,每次询问区间$[li,ri]$的子区间中,f的最大值。
可以发现,$f([l,r])$迭代到倒数第二层,会变成$f(f([l,r-1]),f([l+1, r]))=f([l, r-1])\oplus f([l+1, r])$。因此这个就变成区间dp水题了。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=5005;
int n, q, f[maxn][maxn], maxm[maxn][maxn]; //f[i][j]储存f(ai~aj)的值
int main(){
scanf("%d", &n); int k;
for (int i=1; i<=n; ++i){
scanf("%d", &f[i][i]);
maxm[i][i]=f[i][i];
}
for (int i=2; i<=n; ++i) //区间长度
for (int j=1; j<=n-i+1; ++j){ //区间起点
k=j+i-1; //区间终点
f[j][k]=f[j][k-1]^f[j+1][k];
maxm[j][k]=max(maxm[j][k-1], maxm[j+1][k]);
if (f[j][k]>maxm[j][k]) maxm[j][k]=f[j][k];
}
scanf("%d", &q); int l, r;
for (int i=0; i<q; ++i){
scanf("%d%d", &l, &r);
printf("%d\n", maxm[l][r]);
}
return 0;
}