1. 程式人生 > >Hihocoder 1496 尋找最大值(狀態壓縮 + 高位前綴和)

Hihocoder 1496 尋找最大值(狀態壓縮 + 高位前綴和)

ems sca 題目 二進制 包含 aps void post 前綴

題目鏈接 Hiho 1496

設$f[i]$為二進制集合包含$i$的最大的兩個數,這個東西用高維前綴和維護。

高位前綴和轉移的具體方案 :枚舉每一位,然後枚舉每個集合,大的轉移到小的。

註意合並的時候最好別用$std::sort$(我一開始被卡常數了)

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define fi		first
#define se		second

typedef long long LL;
typedef pair <int, int> PII;

int T;
int n;
int c[6];
PII f[(1 << 20) + 10];
LL  ans;


inline void up(PII &a, PII b){
	if (b.fi > a.fi){
		a.se = a.fi;
		a.fi = b.fi;
	}

	else if (b.fi > a.se){
		a.se = b.fi;
	}

	if (b.se > a.fi){
		a.se = a.fi;
		a.fi = a.se;
	}

	else if (b.se > a.se){
		a.se = b.se;
	}
}

int main(){

	scanf("%d", &T);
	while (T--){
		scanf("%d", &n);
		memset(f, -1, sizeof f);

		rep(i, 1, n){
			int x;
			scanf("%d", &x);
			if (~f[x].fi) f[x].se = x;
			else f[x].fi = x;
		}

		rep(i, 0, 19){
			rep(j, 0, (1 << 20) - 1){
				if ((1 << i) & j){
					up(f[j ^ (1 << i)], f[j]);
				}
			}
		}

		ans = 0;
		rep(i, 0, (1 << 20) - 1) if ((~f[i].fi) && (~f[i].se)) ans = max(ans, 1ll * i * f[i].fi * f[i].se);
		printf("%lld\n", ans);
	}

	return 0;
}

  

Hihocoder 1496 尋找最大值(狀態壓縮 + 高位前綴和)