[题解] CF1554B Cobb

[题解] CF1554B Cobb

传送门

题意

给出一个长度为 \(n\) 的数列,求出 \(i\times j-k\times (a_i|a_j)\) 的最大值。

解题报告

严格做法其它题解已经讲的很明白了,来一个玄学做法。

考场上就感觉这个东西肯定不是全扫过一遍的。

我们可以把结果分成两项来看:\(i\times j\)\(k\times (a_i|a_j)\)

我们希望前一部分尽量大,后一部分尽量小,考虑到 一个数按位或上另一个数数值不会减小,所以如果当前答案 \(ans\leq i\times (i-1)-k\times a_i\),那么就没必要往前扫描找到最大值。

否则的话,往前扫描更新 \(ans\)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
template <typename T>
inline T read(){
	T x=0;char ch=getchar();bool fl=false;
	while(!isdigit(ch)){if(ch=='-')fl=true;ch=getchar();}
	while(isdigit(ch)){
		x=(x<<3)+(x<<1)+(ch^48);ch=getchar();
	}
	return fl?-x:x;
}
#define read() read<int>()
#define LL long long
const int maxn = 1e6 + 10;
int T,n;
LL a[maxn],ans,k;
int main(){
	//freopen("1.in","r",stdin);
	//freopen("1.out","w",stdout);
	T=read();
	while(T--){
		ans=-0x7fffffffffffffff;
		n=read();k=read<LL>();
		for(int i=1;i<=n;i++)a[i]=read<LL>();
		for(int i=n;i>1;i--){
			if(ans<1LL*i*(i-1)-k*a[i]){
				for(int j=i-1;j>=1;j--)ans=max(ans,1LL*i*j-k*(a[i]|a[j]));
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}
posted @ 2021-08-12 18:32  ¶凉笙  阅读(48)  评论(0编辑  收藏  举报