B. Cobb
题意:求
i
∗
j
−
k
∗
(
a
[
i
]
∣
a
[
j
]
)
i * j - k * (a[i] | a[j] )
i∗j−k∗(a[i]∣a[j]) 的最大值。
题解:因为区间太长不能n^2遍历,所以我们希望找到一组f(i,j), i~j区间尽可能小,遍历的范围尽可能小。
因为题目给出的长度是 n ,所以以下说的 j 与 n 等价。
对于一组
f
(
i
,
j
)
=
i
∗
j
−
k
∗
(
a
[
i
]
∣
a
[
j
]
)
f(i,j)= i * j - k * (a[i] | a[j] )
f(i,j)=i∗j−k∗(a[i]∣a[j]) 。它一定是存在一组(i,j)使得f(i,j)取得最大值。
因为
k
∗
(
a
[
i
]
∣
a
[
j
]
)
k * (a[i] | a[j])
k∗(a[i]∣a[j])最大值是2kn,最小值是0。所以我们能找到一组“ 最差的最优解 ”。
最差指的是负影响2kn最大,最优解指的是 i* j 已经是最大的正影响了。所以不存在一组比
(
n
−
1
)
∗
(
n
)
(n-1)*(n)
(n−1)∗(n) -
2
k
n
2kn
2kn 更差的解(这里的不会更差指的是,目测来讲,区间最终取得的最大值一定>=当前这个解)。
所以对于f(i,j)来说,我们希望筛掉一定比当前 "最差的最优解 ”更差的那些数。所以如果f(i,j)的最大值都小于当前 "最差的最优解 ”,那么这段区间就没有意义!
又因为对于任意区间f(i,j),以i为左端点向右循环枚举的时候,最大值为 i * j - 0。
所以如果
m
a
x
max
max
f
(
i
,
j
)
f (i,j)
f(i,j) <
(
n
−
1
)
∗
(
n
)
(n-1)*(n)
(n−1)∗(n) -
2
∗
k
∗
n
2*k*n
2∗k∗n,都应该舍去。
那最终只需要遍历的区间就是
i
>
n
−
2
∗
k
i>n−2∗k
i>n−2∗k这个区间
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int a[N];
int n,k;
int main()
{
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
LL res=-1e9;
for(int i=max(1,n-2*k);i<=n;i++)
for(int j=i+1;j<=n;j++)
res=max(res,(LL)i*j-k*(a[i]|a[j]));
printf("%lld\n",res);
}
return 0;
}