题目链接 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 ", ans); } return 0; }