将出现的数放入一个集合。从大到小枚举每个答案,枚举答案对应的二进制串,再枚举集合剩余元素,存在此元素与二进制串异或后的数就记录答案并删去这个元素。
不知道复杂度多少,但可以通过本题和加强版。
如果复杂度不对,请给出 hack 数据
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
int n,m;
vector<int> f[N];
int a[N];
int ans[N];
set<int> s;
vector<int> p[N];
bool h[N];
signed main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>m>>n;
char c;
int tmp;
for(int i=1;i<=n;i++)
{
tmp=0;
for(int j=1;j<=m;j++)
{
tmp<<=1;
cin>>c;
if(c=='G')tmp|=1;
}
f[tmp].push_back(i);
s.insert(tmp);
h[tmp]=1;
}
for(int i=0;i<(1<<m);i++)
{
p[__builtin_popcount(i)].push_back(i);
}
for(int i=m;i>0;i--)
{
for(auto j=s.begin();j!=s.end();)
{
tmp=*j;
for(auto e:p[i])
{
if(h[tmp^e])
{
for(auto o:f[tmp])
{
ans[o]=i;
}
j=s.erase(j);
tmp=-1;
break;
}
}
if(tmp!=-1)j++;
}
}
for(int i=1;i<=n;i++)
{
cout<<ans[i]<<'\n';
}
}