Loading

讨bitset檄文

引子

万户涕泪,一人冠冕,其心尚有“共和”二字存耶?既忘共和,即称民贼。吾侪昔以大仁大义铸此巨错,又焉敢不犯难,誓死戮此民贼,以拯吾民。

今长江大河,万里以内,武汉京津,扼要诸军,皆已暗受旗帜,磨剑以待。一旦义旗起,呼声动天地。当以秦陇一军,出关北指;川楚一军,规画中原;闽粤旌旗横海,合齐鲁以捣京左。三军既兴,我将与诸君子扼扬子江口,定苏浙,以树东南之威。掣庭扫穴,共戮国贼,期可指日待焉。书曰:“民惟邦本,本固邦宁。”又曰:“纣有臣亿万,惟亿万心。予有臣三千,惟一心。”正义所至,何坚不破?愿与爱国之豪俊共图之!


bitset实际上是通过固定优化,使得一个字节的八个比特能分别储存 8 位的 0/1。对于一个 4 字节的 int 变量,在只存 0/1 的意义下,bitset 占用空间只是其\( [\frac{1}{32}]\),计算一些信息时,所需时间也是其$[\frac 1{32}] $。一般来说可以将原时间复杂度为 \(O(Q)\)的程序,优化为\(O( \frac Q w)\) ,其中为\(w\)为计算机位数。


基本操作

  1. 初始构造
bitset<1000> bs;// a bitset with 1000 bits

bitset()//每一位都是 false。
bitset(unsigned long val)://设为 val 的二进制形式,bitset 二进制由低位至高位存储
bitset(const string& str)://设为01串 str。
  1. 运算符 总之就是支持各种位运算
operator []//访问其特定的一位。

operator == !=//比较两个 bitset 内容是否完全一样。

operator & | ^ &= |= ^= ~//进行按位与/或/异或/取反操作。


//注意:bitset 只能与 bitset 进行位运算,若要和整型进行位运算,要先将整型转换为 bitset。

operator << >> <<= >>=//进行二进制左移/右移。
  1. 成员函数:这里只提几个常用的,如有需要可以去\(OI-wiki\)上翻
count()//返回 true 的数量
size()//返回 bitset 的大小
any()// 若存在某一位是 true 则返回 true,否则返回 false
none()// 若所有位都是 false 则返回 true,否则返回 false
all()//若所有位都是 true 则返回 true,否则返回 false
set()//将整个 bitset 设置成 true
set(pos, val = true)//将某一位设置成 true/false
reset()// 将整个 bitset 设置成 false
reset(pos)//将某一位设置成 false相当于 set(pos, false)
flip()//翻转每一位,相当于异或一个全是 [1] 的 bitset
flip(pos)// 翻转某一位

P1356 数列的整除性

思路很好想,明显可以用bitset优化


POJ 2443 Set Operation

大概题意是给你n个集合,询问是否存在一个集合同时存在x,y。
直接将\(bool\)改为\(bitset\)即可


简单瞎搞题

emmm,很简单的柿子,我们发现空间达到了\(1e8\),原题只给了\(32M\),很自然想到用bitset来优化

f[0].flip(0);
for(int i=1;i<=n;i++) {
   l=read(),r=read();
   for(int j=l;j<=r;j++) f[i]|=(f[i-1]<<(j*j));
}

Backpack(2022“杭电杯”)

柿子很好想 \(f_{i,j,k}|=f_{i-1,j \oplus w,k-v}\)

复杂度不对? \(bitset!\)

int p=1;f[0][0][0]=1;
for(int i=1;i<=n;i++) {
    for(int j=0;j<1024;j++)
      f[p][j]=f[p^1][j^w[i]]<<v[i]|f[p^1][j];
	p^=1;
}
int sum=0;
for(int i=0;i<1024;i++) 
    if(f[n&1][i][m]) sum=i;

[ABC258G] Triangle

根号分治,没啥好说的


P5670 异或秘籍

只关心\(m\)个二进制位,那么是不是高位就没有意义了?

考虑取模,维护各个数字是否存在,想想bitse注意上的数是否存在

加上一个数k,实际就相当于\(t[p]=(t[p]<<k)|(t[p]>>1024-k)\),注意不能只维护小于\(2^m\)的数,因为关注的是二进制位,所以保留多少要与值域有关

线段树维护即可,码有点长,不放


CF633G

和上面的思路一样,维护每个数字是否出现即可,当然还有一个抽象思路,这里不再叙述

这道题非常的好,顺便把树剖给大家复习了


P3674 小清新人渣的本愿

插个眼先

posted @ 2025-03-17 22:26  Mortis_Life  阅读(71)  评论(2)    收藏  举报