[CF251D] Two Sets
Two Sets
因为和最大,从高位向低位考虑,称 n 个元素的异或和为 SUM,若 SUM 这一位为0,则两堆都分配1一定更优,否则为了第一堆尽量小我们把偶数个1分给第一堆,高斯消元即可,因为是01矩阵用 bitset 优化一下。
其实因为我们是动态列出等式所以处理过程与线性基类似。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<bitset>
using namespace std;
#define db double
#define ll long long
#define ull unsigned long long
#define ld long double
#define b1t bitset
const int Mod=998244353;
const int MAXN=1e5+5;
const int UP=62;
void read(int &x){
x=0;int f=1;char s=getchar();
while(s<'0'||s>'9'){
if(s=='-') f=-1;s=getchar();
}
while(s>='0'&&s<='9'){
x=(x<<3)+(x<<1)+(s^48);s=getchar();
}
x*=f;
}
int n,wz[UP],res[MAXN],cnt;
ll a[MAXN],sum;
b1t<MAXN> b[UP];
int main(){
scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sum^=a[i];
for(int op=0;op<2;op++){
for(int i=62;i>=0;i--){
if(((sum>>i)&1)==op){
cnt++;b[cnt][n+1]=op^1;
for(int j=1;j<=n;j++){
if((a[j]>>i)&1) b[cnt][j]=1;
}
for(int j=1;j<cnt;j++){
if(b[cnt][wz[j]]) b[cnt]^=b[j];
}
for(int j=1;j<=n;j++){
if(b[cnt][j]){
wz[cnt]=j;break;
}
}
if(!wz[cnt]){
cnt--;continue;
}
for(int j=1;j<cnt;j++){
if(b[j][wz[cnt]]) b[j]^=b[cnt];
}
}
}
}
for(int i=1;i<=cnt;i++) res[wz[i]]=b[i][n+1];
for(int i=1;i<=n;i++) printf("%d ",2-res[i]);
return 0;
}
本文来自博客园,作者:{StranGePants},转载请注明原文链接:https://www.cnblogs.com/StranGePants/p/17788303.html