以codeforces上的ASC28J为例,讲了一些我遇到的Bitset的题目及做法
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<functional>
#include<string>
#include<algorithm>
#include<time.h>
#include<bitset>
void fre(){freopen("triatrip.in","r",stdin);freopen("triatrip.out","w",stdout);}
template <class T> inline void scand(T &x){char c;x=0;while((c=getchar())<'0');while(c>='0'&&c<='9')x=x*10+(c-48),c=getchar();}
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned int UI;
template <class T> inline void gmax(T &a,T b){if(b>a)a=b;}
template <class T> inline void gmin(T &a,T b){if(b<a)a=b;}
using namespace std;
const int N=1515,M=0,Z=1e9+7,maxint=2147483647,ms31=522133279,ms63=1061109567,ms127=2139062143;
int n,i,j;
char s[N];
/*
【算法介绍】
bitset是可以类似于状压DP,可以对01状态进行压缩和表示。
<1>bitset不仅限于32bits or 64bits,而是可以达到甚至是1e8 bits
<2>bitset支持or and xor << >> 等位运算,效率很高
其常用函数如下:
b.any() 判断b中是否存在值为1的二进制位
b.none() 判断b中是否不存在值为1的二进制位
b.count() 判断b中值为1的二进制位个数
b.size() 判断b中二进制位的个数
b[pos] 访问b中在pos处的二进制位
b.test(pos) 判断b中在pos处的二进制位是否为1
b.set() 把b中所有二进制位都置为1
b.set(pos) 把b[pos]置为1
b.reset() 把b中所有二进制位都置为0
b.reset(pos) 把b[pos]置为0
b.flip() 把b中所有二进制位逐位取反
b.flip(pos) 把b[pos]取反
scanf("%lld", &e); cout << e << endl; //对bitset做读入或输出,输出的位置关系为高位 -> 低位
e[pos] = 1; cout << e << endl; //pos的位置关系在bitset上,相对位置关系为高位 -> 低位
使得e <<= 1相当于对于所有的x,都有e[x] = e[x - 1]
UI* v = (UI*)&T; //把bitset转化为UI的数组
使用举例1 ASC28J:------------------------------------
http://codeforces.com/gym/100342/attachments/download/2145/20072008-winter-petrozavodsk-camp-andrew-stankevich-contest-28-asc-28-en.pdf
[题意]
给你一个可达1500大小的01矩阵,b[i][j]==1表示从i到j有边。
问你这个图中含有多少个三元环。
[分析]
最暴力的O(n^3)做法是——
for(i=0;i<n;i++)for(j=0;j<n;j++)for(k=0;k<n;k++)
if(a[i][j]&&a[j][k]&&a[k][i])ans++;
但这个时间复杂度是O(n^3),于是想到用bitset优化
如果有(j->i)以及(i->k)边和(k->j)边,那么就构成了一个三元环。
于是for(i=0;i<n;i++)for(j=0;j<n;j++)if(out[j][i])
ans+=(out[i]&in[j]).count();
(i->0)(i->1)(i->2)...(i->n)
(0->j)(1->j)(2->j)...(n->j)
两者&一下,然后再count()一下。就AC啦
使用举例2 TOJ4119:------------------------------------
1个bool是1字节,8个bitset单位才是1字节。
所以,用bool可以实现的,几乎都可以用bitset优化时间复杂度+空间复杂度
使用举例3 HDU5313 or GYM100781F ----------------------
注意,bitset可以说b[0]是最低位,
左移<<=会使得其变大