思路
面对位运算,而且要求答案最大,我们应该想到一个贪心:从二进制最高位开始取,这样能保证答案最优
对于一个答案 \(x\) ,它可行当且仅当存在 \(i<j<k\),满足有 \(x\oplus w \subseteq a[i]\) 和 \(w\subseteq a[j],a[k]\)(这里 \(w\subseteq x\))
我们考虑记录 \(Mn[w]\) 为 \(w\subseteq a[i]\) 时 \(i\) 的最小值,\(Mx[w]\) 为 \(w\subseteq a[i]\) 时 \(i\) 的最大值(需要同时记录两个,因此要用二元组记录最大和次大)
显然可以用高维前缀和来完成
验证答案 \(x\) 是否可行时,我们只需要判断是否有 \(Mn[x\oplus w]<Mx[w]\)(\(w\subseteq x\))即可
代码
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#define LL long long
#define FOR(i, x, y) for(int i = (x); i <= (y); i++)
#define ROF(i, x, y) for(int i = (x); i >= (y); i--)
#define PFOR(i, x) for(int i = he[x]; i; i = r[i].nxt)
inline int reads()
{
int sign = 1, re = 0; char c = getchar();
while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();}
while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();}
return sign * re;
}
#define pii std::pair<int, int>
#define mp std::make_pair
int n, a[1000005], Mn[(1 << 21)], ans;
pii Mx[(1 << 21)];
inline pii ud(pii a, pii b)
{
int s[4]; s[0] = a.first, s[1] = a.second, s[2] = b.first, s[3] = b.second;
std::sort(s, s + 4); return mp(s[3], s[2]);
}
inline bool chk(int x)
{
for(int i = x; i; i = (i - 1) & x) if(Mn[x ^ i] < Mx[i].second) return 1;
return (Mn[x] < Mx[0].second);
}
signed main()
{
#ifndef ONLINE_JUDGE
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
n = reads();
memset(Mn, 63, sizeof(Mn));
FOR(i, 1, n) a[i] = reads(), Mn[a[i]] = std::min(Mn[a[i]], i);
FOR(i, 1, n) Mx[a[i]] = ud(Mx[a[i]], mp(i, 0));
FOR(i, 0, 20) ROF(j, (1 << 21) - 1, 0)
if(!(j & (1 << i)))
Mn[j] = std::min(Mn[j], Mn[j ^ (1 << i)]),
Mx[j] = ud(Mx[j], Mx[j ^ (1 << i)]);
ROF(i, 20, 0)
if(chk(ans | (1 << i))) ans |= (1 << i);
printf("%d", ans);
return 0;
}
标签:CF1208F,int,Mn,sign,Pieces,答案,include,Bits,define
From: https://www.cnblogs.com/zuytong/p/16581977.html