bitset在位运算中的妙用
bitset
以前没有留意到那么好用的东西,可能好久以前做过一次要用bitset优化的题目但是没有记录下来,这次在洛谷基础赛 #21的B题发现可以用bitset或许会更方便于是打算写一个blog概述一下。
bitset在oi wiki
代码解释:
#include <bitset>
//使用bitset必要的头文件
bitset<N> Bs;
//构建一个长度为N(有N个01串)的bitset
//一般默认全为false -> 0
运算符
operator []: 访问其特定的一位。
operator ==/operator !=: 比较两个 bitset 内容是否完全一样。
operator &/operator &=/operator |/operator |=/operator ^/operator ^=/operator ~: 进行按位与/或/异或/取反操作。
注意:bitset 只能与 bitset 进行位运算,若要和整型进行位运算,要先将整型转换为 bitset。
operator <</operator >>/operator <<=/operator >>=: 进行二进制左移/右移。
此外,bitset 还提供了 C++ 流式 IO 的支持,这意味着你可以通过 cin/cout 进行输入输出。
成员函数
count(): 返回 true 的数量。
size(): 返回 bitset 的大小。
test(pos): 它和 vector 中的 at() 的作用是一样的,和 [] 运算符的区别就是越界检查。
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(): 翻转每一位。(0\leftrightarrow1,相当于异或一个全是 1 的 bitset)
flip(pos): 翻转某一位。
例题
Problem A: P12245 共同兴趣
My accept code:
//P12245
#include <iostream>
#include <bitset>
#define ll long long
using namespace std;
bitset<510> bs[100010];
bitset<510> BS;
bitset<510> Bstag;
ll F[510];
ll dp[510];
int main()
{
ll N,M,a;
cin>>N>>M;
for(int i=1; i<=M; i++)
{
cin>>F[i];
if(F[i])
bs[1].set(i,true);
//设置第i(必须是F[i] = 1时)位为1,其余为0
}
for(int i=2; i<=N; i++)
{
for(int j=1; j<=M; j++)
{
cin>>a;
if(a)
bs[i].set(j,true);
//同理,设置a=1时相应位置为1,其余为0
}
}
for(int i=2; i<=N; i++)
{
ll Max = 0;
for(int j=2; j<=N; j++)
{
BS = bs[i] & bs[j];
//进行和运算,求出当前学生与其他学生的最大兴趣值
//cout<<BS.count()<<endl;
ll Ftag = BS.count();
//count()用于输出bs[i]和bs[j]中和运算出来的1的个数
if(i != j)
Max = max(Max,Ftag);
}
dp[i] = Max; //记录下来
}
ll Max = 0;
for(int r=1; r<=M; r++)
{
Bstag = bs[1];
Bstag.set(r,true);
//遍历每一位,因为每一位都可能变成1,每次的询问独立,故用 Bstag
ll ans = 0;
for(int i=2; i<=N; i++)
{
BS = bs[i] & Bstag;
//cout<<BS.count()<<endl;
ll Ftag = BS.count();
if(Ftag >= dp[i])
ans ++;
}
Max = max(Max,ans);
} cout<<Max;
return 0;
}

浙公网安备 33010602011771号