[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;
}
posted @ 2023-10-25 22:34  StranGePants  阅读(8)  评论(0编辑  收藏  举报