8.15 bitset(位图)详细用法及应用举例


一、介绍

std::bitset 是标准库中的一个存储 0/1 大小不可变容器。通俗讲,bitset 相当于一个二进制的数组,并且可以直接用01串赋值

1.1 复杂度

由于内存地址是按字节即 byte 寻址,而非比特 bit,一个 bool 类型的变量,虽然只能表示 0/1, 但是也占了 1 byte 的内存。bitset 就是通过固定的优化,使得一个字节的八个bit能分别储存 8 位的 0/1。对于一个 4 字节的 int 变量,在只存 0/1 的意义下,bitset 占用空间只是其 1/32;计算一些信息时,所需时间也是其 1/32

在某些情况下通过== bitset 可以优化程序的运行效率==。至于其优化的是复杂度还是常数,要看计算复杂度的角度。一般 bitset 的复杂度为:(设原复杂度为O(n) )==O(n/32)==这种记法不太严谨(复杂度中不应出现常数),但体现了 bitset 能将所需时间优化至 1/32

二、基本操作

/*bitset*/
#include<bits/stdc++.h>
using namespace std;
int main(){
	//构造函数:
	//bitset<n> b;b有n位,每位都为0.参数n可以为一个表达式
	bitset<5>b;
	cout<<b<<endl;//00000
	//bitset<n> b(unsigned long u);b有n位,并用u赋值;如果u超过n位,则顶端被截除;如果U不足n位,则在前端补0 
	bitset<5>b1(5); 
	cout<<b1<<endl;//00101
	//bitset<n> b(string s);b是string对象s(01串)中含有的位串的副本
	string s ( "10011" );
	bitset<5> b2(s);
	cout<<b2<<endl;//10011
	
	//[]: 访问其特定的一位
	cout<<b2[0]<<' '<<b2[2]<<endl;//1  0
	
	//set(): 将整个 bitset 设置成 true
	//set(pos, val = true): 将某一位设置成 true/false
	b.set();
	cout<<b<<endl;//11111 
	
	//count(): 返回 true (1)的数量
	cout<<b.count()<<endl;//0
	cout<<b1.count()<<endl;//2
	//size(): 返回 bitset 的大小
	cout<<b.size()<<endl;//5
	
	//any(): 若存在某一位是 true 则返回 true,否则返回 false
	if(b.any()) cout<<"存在某一位是1"<<endl;//存在某一位是1
	else cout<<"全是0"<<endl;
	
	//to_string(): 返回转换成的字符串表达
	cout<<b.to_string()<<endl;//11111
	//to_ulong(): 返回转换成的 unsigned long 表达 ;
	//to_ullong():返回转换成的 unsigned long long 表达
	cout<<b2.to_ulong()<<endl;//19
	
	//_Find_first(): 返回 bitset 第一个 true 的下标,若没有 true 则返回 bitset 的大小
	cout<<b2._Find_first()<<endl;//0
	//_Find_next(pos): 返回 pos 后面(下标严格大于 pos 的位置)第一个 true 的下标,若 pos 后面没有 true 则返回 bitset 的大小
	
	//运算符 
	cout<<(b>>1)<<endl;//01111 (右移,不赋值)
	cout<<b<<endl;//11111
	cout<<(b<<=2)<<endl;//11100(左移2位,低位补0,有自身赋值)
	cout<<b<<endl;//11100
	//b=11100 b1=00101
	cout<<(b1^=b)<<endl;//11001(b1对b按位异或后赋值给b1)
	cout<<b<<' '<<b1<<endl;//11100  11001
	cout<<(b1&=b)<<endl;//11000(b1对b按位与后赋值给b1)
	cout<<(b1|=b)<<endl;//11100(b1对b按位或后赋值给b1)
}

三、应用举例

「LibreOJ β Round #2」贪心只能过样例

/*简单 DP+bitset*/
#include<bits/stdc++.h>
using namespace std;
bitset<1000005>bb[105];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	int n,a,b;
	cin>>n; 
	bb[0]=1;
	//cout<<bb[0]<<endl;
	for(int i=1;i<=n;i++){
		cin>>a>>b;
		for(int j=a;j<=b;j++){
			bb[i]|=bb[i-1]<<(j*j);//第i个数=第i-1个数+j*j,也就是所有1左移j*j的位置
		}
	}
	cout<<bb[n].count();
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值