【算法竞赛学习笔记】Bitset详解和应用

本文介绍了位集(bitset)数据结构,包括其特性、声明方式、常用方法以及在ACM竞赛和数据结构问题中的优化应用,如传递闭包、动态规划转移、区间操作等。位集因其支持位运算、节省空间和优化时间而成为解决特定问题的利器。

title : bitset
date : 2021-8-20
tags : ACM,数据结构
author : Linno


Bitset

bitset是一种类似数组的数据结构,它的每一个元素只能是0或1,每个元素只用1bit的空间。可以使用只包含‘0’或‘1’的字符串构造。

优点

支持所有的位运算。

空间占用非常小,也可用于优化时间。

声明方式

#include<bitset>
bitset<30>bi;

string s="100101";
bitset<10>bs(s); //长度为10,前面用0补充
cout<<bs<<endl; //0000100101
cout<<bs[0]<<endl; //下标是从右到左的,可以像数组一样访问每一位

方法

bi.size() //返回大小,即位数
bi.count() //返回1的个数
bi.any() //返回是否有1
bi.none() //返回是否没有1
bi.set() //全部变成1
bi.set(p)//将第p+1位变成1
bi.set(p,x)//将p+1位变成x
bi.reset() //全部变成0
bi.reset(p) //将p+1位变成0
bi.flip() //全部取反
bi.flip(p) //将p+1位取反
bi.test(p) //返回i的索引,如果不存在则返回0
bi.to_ulong() //返回它转换为unsigned long的结果,如果超出范围则报错
bi.to_ullong() //返回它转换为unsigned long long的结果
bi.to_string() //返回它转换位string的结果

bitset优化传递闭包

[JSOI2010]连通数
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int maxn=2007;

bitset<maxn>bi[maxn];
int n,ans=0;
string str;

signed main(){
   
   
	cin>>n;
	for(int i=1;i<=n;i++){
   
   
		cin>>str;
		for(int j=1;j<=n;j++)
			bi[i][j]=(str[j-1]=='1'||i==j)?1:0;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			if(bi[j].test(i)) bi[j]|=bi[i];
	for(int i=1;i<=n;i++) ans+=bi[i].count();
	cout<<ans<<endl;
	return 0;
}

bitset优化Dp转移

转移式dp[i][k]∣=dp[i−1][k−j∗j]dp[i][k]|=dp[i-1][k-j*j]dp[i][k]=dp[i1][kjj]

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define int long long
using namespace std;
const int N=105;
bitset<N*N*N>dp[N];
int n,ans=0;
int l[N],r[N];

signed main(){
   
   
	cin>>n;
	for(int i=1;i<=n;i++){
   
   
		cin>>l[i]>>r[i];
	}
	dp[0].set(0);
	for(int i=1;i<=n;i++){
   
   
		for(int j=l[i];j<=r[i];j++){
   
   
			dp[i]|=dp[i-1]<<(j*j);
		}
	}
	cout<<dp[n].count()<<"\n";
	return 0;
}
luoguP1537 弹珠

01背包+bitset优化,效率非常优秀。

题意是:有1~6大小的若干个弹珠,要求能否平分总数。

#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;

int read(){
   
   	int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){
   
   if(ch=='-') f=f*-1;ch=getchar();}while(ch>='0'&&ch<='9'){
   
   x=x*10+ch-'0';ch=getchar();}return x*f;}

int sum,s[10],idx=0;
bitset<20010>frog;

void clear()
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RWLinno

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值