https://codeforces.com/problemset/problem/1361/C
从高到低位枚举,如果一个项链的答案是ans,那么根据题意等价于这些连接之间末位的ans个bits是相同的,把一对珍珠当一条边,连接末位的bits之间的连线,然后跑欧拉回路,记录边的顺序就行了
从标程里学习了递归的欧拉回路写法,方便记录边的序号,还学了新的输出姿势,涨姿势了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fir first
#define sec second
typedef pair<int,int> p;
const int maxl=1<<20;
int n,m,cas,k,cnt,tot,ansb;
int a[maxl][2],du[maxl],ans[maxl];
int s[maxl],cur[maxl];
bool in[maxl],vis[maxl];
vector <p> e[maxl];
inline void prework()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i][0],&a[i][1]);
}
inline void dfs(int u)
{
vis[u]=true;
for(p d:e[u])
if(!vis[d.fir])
dfs(d.fir);
}
inline bool jug(int mask)
{
for(int i=0;i<=mask;i++)
e[i].clear(),vis[i]=false;
int u,v,len,cnt;
for(int i=1;i<=n;i++)
{
u=a[i][0]&mask;v=a[i][1]&mask;
e[u].push_back({v,2*i+1});
e[v].push_back({u,2*i});
}
cnt=0;
for(int i=0;i<=mask;i++)
{
len=e[i].size();
if(len&1)
return false;
if(!vis[i] && len>0)
{
if(cnt>0) return false;
cnt++,dfs(i);
}
}
return true;
}
inline void eular(int u,int pre=-1)
{
while(e[u].size())
{
p d=e[u].back();
e[u].pop_back();
if(in[d.sec/2])
continue;
in[d.sec/2]=true;
eular(d.fir,d.sec);
}
if(pre!=-1)
{
ans[++ans[0]]=pre;
ans[++ans[0]]=pre^1;
}
}
inline void solv(int mask)
{
int len,u,i;
for(int st=0;st<=mask;st++)
{
len=e[st].size();
if(len>0)
{
eular(st);
return;
}
}
}
inline void mainwork()
{
for(int i=20;i>=0;i--)
if(jug((1<<i)-1))
{
solv((1<<i)-1);ansb=i;
return;
}
}
inline void print()
{
printf("%d\n",ansb);
for(int i=1;i<=2*n;i++)
printf("%d%c",ans[i]-1," \n"[i==2*n]);
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}