2016 年第一题献给 CF 了!
题意:n 个数,m 次询问,每次询问给出左右端点,求出区间内任意两个数 f(x,y)的最大值。其中 f(x,y)=x^(x+1)^…^y. (x<=y).
思路:预处理出 1~n 的连续异或的结果。用两重循环遍历所有两两组合,内部循环标记右侧端点最大值,内部循环结束后遍历所有询问更新结果。
#include<iostream>
#include<cmath>
#include<queue>
#include<cstring>
#include<string>
#include<map>
#include<stack>
#include<set>
#include<cstdio>
#include<algorithm>
using namespace std;
int y[1000005];
int main(){
//freopen("a.txt", "r", stdin);
y[0]=0;
for(int i = 1; i <= 1000002; i++) //预处理
y[i] = y[i-1]^i;
int n, m;
while(scanf("%d %d", &n, &m) != EOF){
int a[50005], l[5005], r[5005];
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for(int i = 1; i <= m; i++)
scanf("%d %d", &l[i], &r[i]);
int ans[5005];
memset(ans, 0, sizeof(ans));
for(int i = 1; i <= n; i++){
int qq[50005]; //qq[j]代表i到j区间内最大值
for(int j = i; j <= n; j++){
int minn = min(a[i], a[j]);
int maxx = max(a[i], a[j]);
if(j == i) qq[j] = y[maxx]^y[minn-1];
else qq[j] = max(qq[j-1], y[maxx]^y[minn-1]);
}
for(int k = 1; k <= m; k++){ //更新所有询问的答案
if(i>=l[k] && i<=r[k]){
ans[k] = max(ans[k], qq[r[k]]);
}
}
}
for(int i = 1; i <= m; i++)
cout << ans[i] << endl;
}
return 0;
}