卧薪尝胆,厚积薄发。
XOR-pyramid
Date: Thu Sep 20 17:03:59 CST 2018 In Category: NoCategory

Description:

设 $f(b)=b[1](m=1)/f(b[1]\text{ xor }b[2],b[2]\text{ xor }b[3],\dots,b[m-1]\text{ xor }b[m])(m\ne 1)$ 。
给一个数列, $q$ 次询问每次给出一个区间询问最大区间 $f$ 和。
$1\le n \le 5000,1\le q \le 100000$

Solution:

首先证明一个结论: $f(1\sim n)=f(1\sim n-1)\text{ xor }f(2\sim n)$ 。
首先 $f(b[1],b[2])=f(b[1]\text{ xor }b[2])=b[1]\text{ xor }b[2]=f(b[1])\text{ xor }f(b[2])$ 。
下面证明若长度为 $m-1$ 的序列都满足,那么长度为 $m$ 的序列也满足。
$f(b[1],b[2],\dots,b[m])=f(b[1]\text{ xor }b[2],b[2]\text{ xor }b[3],\dots,b[m-1]\text{ xor }b[m])$ ,可以应用数学归纳法,原式 $=f(b[1]\text{ xor }b[2],b[2]\text{ xor }b[3],\dots,b[m-2]\text{ xor }b[m-1])\text{ xor }f(b[2]\text{ xor }b[3],b[3]\text{ xor }b[4],\dots,b[m-1]\text{ xor }b[m])$
那么原式 $=f(b[1],b[2],\dots,b[m-1])\text{ xor }f(b[2],b[3],\dots,b[m])$ 。
所以先区间 $DP$ 出每个区间的 $f$ 值,然后 $dp[i][j]=\max(f[i][j],\max(f[i][j-1],f[i+1][j]))$ 预处理出每个区间的子段最大值,询问时直接处理即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,q;
#define MAXN 5010
int f[MAXN][MAXN];
int g[MAXN][MAXN];
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%d",&f[i][i]);
for(int i = 1;i <= n;++i)g[i][i] = f[i][i];
for(int l = 2;l <= n;++l)
{
for(int i = 1;i <= n - l + 1;++i)
{
int j = i + l - 1;
f[i][j] = f[i + 1][j] ^ f[i][j - 1];
g[i][j] = max(f[i][j],max(g[i + 1][j],g[i][j - 1]));
}
}
scanf("%d",&q);
int a,b;
for(int i = 1;i <= q;++i)
{
scanf("%d%d",&a,&b);
printf("%d\n",g[a][b]);
}
return 0;
}
In tag: 玄学
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡