基础用法

C++ Reference

神犇博客

余下的就是例题了

[BZOJ3687]简单题

考虑\(DP\),设\(f[i][j]\)表示前\(i\)个元素的算数和为\(j\)的子集个数,有:

\[f[i][j]=f[i-1][j]+f[i-1][j-a[i]]
\]

时间复杂度为\(O(n\sum a_i)\),显然会超时。

考虑到题目要求计算的是异或和,所以我们实际上只需维护前\(i\)个元素的算数和为\(j\)的子集个数的奇偶性,这个可以使用bitset实现。bitset第\(j\)位为\(1\)代表前\(i\)个元素的算数和为\(j\)的子集个数为奇数,转移时:

\[Bitset=Bitset\ or\ (Bitset<<a[i])
\]

即可。

由于并行运算(我也不知道这是什么东西),时间复杂度为\(O(n\frac{\sum a_i}{32})\)(并且常数好像还很小),只要我们有信仰,就一定可以\(AC\)。

建议做此题之前先翻阅一下BZOJ的讨论区,数据有锅,害的ErkkiErkko怒送\(1TLE+2WA\)。

蒟蒻代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <bitset>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,x) for(int i=head[(x)];i;i=e[i].nxt)
using std::cin;
using std::cout;
using std::endl;
typedef long long LL; inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
} const int MAXN=1005;
const int MAXNUM=2000005;
int n,a[MAXN];
std::bitset<MAXNUM> bs; int main(){
n=read();
bs[0]=1;
int x;
rin(i,1,n){
x=read();
bs^=(bs<<x);
}
int ans=0;
rin(i,0,2000000) if(bs[i])
ans^=i;
printf("%d\n",ans);
return 0;
}

Shift-And&Shift-Or字符串匹配算法

Wikipedia

神犇博客

蒟蒻代码

std::bitset<MAXN> now,sta[30];

Shift-And

rin(i,1,m) sta[t[i]-'a'].set(i-1);
rin(i,1,n){
now=((now<<1).set(0)&sta[s[i]-'a']);
if(now[m-1]) printf("%d\n",i-m+1);
}

Shift-Or

now.set();
memset(sta,0xff,sizeof sta);
rin(i,1,m) sta[t[i]-'a'].reset(i-1);
rin(i,1,n){
now=((now<<1)|sta[s[i]-'a']);
if(!now[m-1]) printf("%d\n",i-m+1);
}

练手题:[BZOJ4503]两个串

这不是FFT模板题吗?

对啊。

虽然这个算法跑得比FFT慢(多了)。

通配符怎么解决啊?

通配呗。

[BZOJ4939][Ynoi2016]掉进兔子洞

这一道题和下一道题大概是我学习bitset的出发点。

一开始想了半天用权值线段树怎么做,然而越想越不可做,套上莫队也不行。于是去百度题解,仿佛打开了通往新世界的大门。

题解告诉我们如果用bitset上的一段连续的位表示对应的一个数出现过几次,于是就可以先用莫队求出三个区间的的权值bitset,然后对这三个的权值bitset做与运算,答案即为\(\sum len-ResultBitset.count()\)。

要特别提到的是,为了节省空间我们需要分批处理询问。

时间复杂度\(O(n \sqrt{n}+\frac{n^2}{32})\)。(不知道这算不算\(O(n^2)\)过\(1e5\))

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <bitset>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,x) for(int i=head[(x)];i;i=e[i].nxt)
using std::cin;
using std::cout;
using std::endl;
typedef long long LL; inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
} const int MAXN=100005;
const int SIZE=340;
const int T=25000;
int n,m,a[MAXN],b[MAXN];
int cnt,ans[T+5],has[MAXN];
std::bitset<MAXN> bs[T+5],now;
struct Qu{
int l,r,lk,id;
inline friend bool operator < (Qu x,Qu y){
if(x.lk!=y.lk) return x.lk<y.lk;
if(x.lk&1) return x.r<y.r;
return x.r>y.r;
}
}q[T*3+5]; inline void mo(){
memset(has,0,sizeof has);
memset(bs,0xff,sizeof bs);
std::sort(q+1,q+cnt+1);
int nowl=1,nowr=0;
now.reset();
rin(i,1,cnt){
while(nowl>q[i].l){
nowl--;
now.set(a[nowl]+has[a[nowl]]);
has[a[nowl]]++;
}
while(nowr<q[i].r){
nowr++;
now.set(a[nowr]+has[a[nowr]]);
has[a[nowr]]++;
}
while(nowl<q[i].l){
has[a[nowl]]--;
now.reset(a[nowl]+has[a[nowl]]);
nowl++;
}
while(nowr>q[i].r){
has[a[nowr]]--;
now.reset(a[nowr]+has[a[nowr]]);
nowr--;
}
bs[q[i].id]&=now;
}
cnt/=3;
rin(i,1,cnt){
printf("%d\n",ans[i]-bs[i].count()*3);
}
} int main(){
n=read(),m=read();
rin(i,1,n){
a[i]=b[i]=read();
}
std::sort(b+1,b+n+1);
rin(i,1,n){
a[i]=std::lower_bound(b+1,b+n+1,a[i])-b;
}
rin(i,1,m){
q[++cnt].l=read();
q[cnt].lk=(q[cnt].l-1)/SIZE+1;
q[cnt].r=read();
q[cnt].id=(i-1)%T+1;
ans[(i-1)%T+1]+=q[cnt].r-q[cnt].l+1;
q[++cnt].l=read();
q[cnt].lk=(q[cnt].l-1)/SIZE+1;
q[cnt].r=read();
q[cnt].id=(i-1)%T+1;
ans[(i-1)%T+1]+=q[cnt].r-q[cnt].l+1;
q[++cnt].l=read();
q[cnt].lk=(q[cnt].l-1)/SIZE+1;
q[cnt].r=read();
q[cnt].id=(i-1)%T+1;
ans[(i-1)%T+1]+=q[cnt].r-q[cnt].l+1;
if(cnt==T*3){
mo();
cnt=0;
memset(ans,0,sizeof ans);
}
}
if(cnt) mo();
return 0;
}

[BZOJ4810][Ynoi2017]由乃的玉米田

话说bitset的骚操作还真多,感觉很难一下子全部掌握。

这道题可以稍微地类比一下生成函数。

莫队求出每个区间的权值bitset。考虑询问,减的话直接右移后做与,加的话再维护一个翻转的权值bitset就好了(有种\(FFT\)画风),乘的话,枚举给定乘积的约数再在bitset里查询即可。

时间复杂度\(O(n \sqrt{n}+\frac{n^2}{32})\)。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <bitset>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
using std::cin;
using std::cout;
using std::endl;
typedef long long LL; inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
} const int MAXN=100005;
const int SIZE=340;
int n,m,a[MAXN],cnt[MAXN];
bool ans[MAXN];
std::bitset<MAXN> f,g;
struct Qu{
int opt,l,r,x,lk,id;
inline friend bool operator < (Qu x,Qu y){
if(x.lk!=y.lk) return x.lk<y.lk;
if(x.lk&1) return x.r<y.r;
return x.r>y.r;
}
}q[MAXN]; int main(){
n=read(),m=read();
rin(i,1,n){
a[i]=read();
}
rin(i,1,m){
q[i].opt=read();
q[i].l=read();
q[i].r=read();
q[i].x=read();
q[i].lk=(q[i].l-1)/SIZE+1;
q[i].id=i;
}
std::sort(q+1,q+n+1);
int l=1,r=0;
rin(i,1,m){
while(l>q[i].l){
l--;
cnt[a[l]]++;
f.set(a[l]);
g.set(MAXN-5-a[l]);
}
while(r<q[i].r){
r++;
cnt[a[r]]++;
f.set(a[r]);
g.set(MAXN-5-a[r]);
}
while(l<q[i].l){
cnt[a[l]]--;
if(!cnt[a[l]]){
f.reset(a[l]);
g.reset(MAXN-5-a[l]);
}
l++;
}
while(r>q[i].r){
cnt[a[r]]--;
if(!cnt[a[r]]){
f.reset(a[r]);
g.reset(MAXN-5-a[r]);
}
r--;
}
if(q[i].opt==1){
if((f&(f>>q[i].x)).any()) ans[q[i].id]=1;
}
else if(q[i].opt==2){
if((f&(g>>(MAXN-5-q[i].x))).any()) ans[q[i].id]=1;
}
else{
int lim=sqrt(q[i].x);
rin(j,1,lim){
if(q[i].x%j) continue;
if(f[j]&&f[q[i].x/j]){
ans[q[i].id]=1;
break;
}
}
}
}
rin(i,1,m){
if(ans[i]) printf("yuno\n");
else printf("yumi\n");
}
return 0;
}

Extra. 三维偏序

这是一个在洛谷的三维偏序模版题会MLE的算法。

把三维分开处理,每次只对其中的一维排序。这样对于每个点很容易算出在这一维不大于这个点的所有点的集合,用bitset存储,最后三个集合求交就好了。

但是我们需要开\(1e5\)个\(1e5\)的bitset,而题目的空间限制是\(512MB\),大概只能开\(4e9\)位,于是就愉快地MLE了。

Update on 2018/12/7:好吧,这里为了卡空间要套个分块,但是在洛咕上会TLE,极限数据\(2.5s+\)。感谢UOJ群的各位和yyb,放个yyb博客的链接在这:链接,yyb orz。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <bitset>
#define rin(i,a,b) for(register int i=(a);i<=(b);i++)
#define rec(i,a,b) for(register int i=(a);i>=(b);i--)
#define trav(i,x) for(register int i=head[(x)];i;i=e[i].nxt)
using std::cin;
using std::cout;
using std::endl;
typedef long long LL; inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
} const int MAXN=100005;
const int SIZE=335;
const int BLOCK=(MAXN>>5)+5;
int n,k,dat[3][MAXN],blg[MAXN],rez[MAXN];
int Table[65536]; inline void init(){
rin(i,0,65535) Table[i]=Table[i>>1]+(i&1);
} inline int query(unsigned int x){
return Table[x>>16]+Table[x&65535];
} struct Bitset{
unsigned int Element[BLOCK],siz;
Bitset(){
siz=0;
}
inline friend void operator &= (Bitset &x,Bitset y){
x.siz=0;
rin(i,0,BLOCK-1) x.Element[i]&=y.Element[i],x.siz+=query(x.Element[i]);
}
inline void set(){
siz=n;
memset(Element,0xff,sizeof Element);
}
inline void set(int x){
int nth=(x>>5),pos=x-(nth<<5);
Element[nth]|=(1u<<pos);
siz++;
}
};
Bitset now,ret,bs[3][MAXN/SIZE+5]; struct Pair{
int x,id;
inline friend bool operator < (Pair x,Pair y){
return x.x<y.x;
}
}a[3][MAXN]; inline int L(int x){
return (x-1)*SIZE+1;
} inline int R(int x){
return x*SIZE;
} inline int find(int d,int x){
int l=1,r=n,retint;
while(l<=r){
int mid=((l+r)>>1);
if(a[d][mid].x<=x) retint=mid,l=mid+1;
else r=mid-1;
}
return retint;
} inline void getset(int d,int x){
int pos=find(d,x);
ret=bs[d][blg[pos]-1];
rin(i,L(blg[pos]),pos) ret.set(a[d][i].id);
} int main(){
n=read(),k=read();
init();
rin(i,1,n){
a[0][i]=(Pair){dat[0][i]=read(),i};
a[1][i]=(Pair){dat[1][i]=read(),i};
a[2][i]=(Pair){dat[2][i]=read(),i};
blg[i]=(i-1)/SIZE+1;
}
rin(d,0,2){
std::sort(a[d]+1,a[d]+n+1);
rin(i,1,blg[n]){
bs[d][i]=bs[d][i-1];
rin(j,L(i),R(i)) bs[d][i].set(a[d][j].id);
}
}
rin(i,1,n){
now.set();
rin(d,0,2) now&=(getset(d,dat[d][i]),ret);
rez[now.siz-1]++;
}
rin(i,0,n-1) printf("%d\n",rez[i]);
return 0;
}

C++ STL bitset总结的更多相关文章

  1. C++ STL bitset 容器详解

    C++ STL bitset 容器详解 本篇随笔讲解\(C++STL\)中\(bitset\)容器的用法及常见使用技巧. \(bitset\)容器概论 \(bitset\)容器其实就是个\(01\)串 ...

  2. STL::bitset

    bitset: A bitset stores bits.大小通过参数传递,在编译时确定.可变的可参考 vector<bool>. constructor default: integer ...

  3. 【转载】【bitset】C++ STL bitset 使用总结

    C++ bitset类的使用与简介 有些程序要处理二进制位的有序集,每个位可能包含的是0(关)或1(开)的值.位是用来保存一组项或条件的yes/no信息(有时也称标志)的简洁方法.标准库提供了bits ...

  4. STL————bitset

    C++的 bitset 在 bitset 头文件中,它是一种类似数组的结构,它的每一个元素只能是0或1,每个元素仅用1bit空间. bitset<> bitset1; //无参构造,长度为 ...

  5. 标准非STL容器 : bitset

    1. 概念 什么是"标准非STL容器"?标准非STL容器是指"可以认为它们是容器,但是他们并不满足STL容器的所有要求".前文提到的容器适配器stack.que ...

  6. BitSet

    前几天干了一件比较无聊的事儿——抄了一遍C++ STL bitset的源代码,把不懂的宏定义去掉了,发现(暂时)还能用,嘿嘿. #ifndef BITSET_H #define BITSET_H #i ...

  7. 史上最全的各种C++ STL容器全解析

    史上最全的C++ STL 容器大礼包 为什么\(C++\)比\(C\)更受人欢迎呢?除了\(C++\) 的编译令人感到更舒适,\(C++\)的标准模板库(\(STL\))也占了很重要的原因.当你还在用 ...

  8. C++STL位标志、智能指针与异常处理

    参考<21天学通C++>第25章节,对STL位标志进行介绍.就是当需要不是像char int long 等整个字节数的数据表示形式,而是使用二进制位表示的时候,通常使用这里讲到的位标志.从 ...

  9. C++——输入、输出和文件

    一.C++输入和输出概述 1.1.流和缓冲区 C++程序把输入和输出看作字节流.输入时,程序从输入流中抽取字节:输出时,程序将字节插入到输出流中.对于面相文本的程序,每个字节代表一个字符,更通俗地说, ...

随机推荐

  1. 【Linux开发】OpenCV在ARM-linux上的移植过程遇到的问题2---CMAKE配置问题

    实际上这里说的是移植的第一步,下载到源码后,我用的是opencv2.4.9,解压缩,然后可以利用cmake-gui来进行configure配置,这里面需要设置交叉编译的工具链,具体的可以参考[Linu ...

  2. 【Linux开发】V4L2应用程序框架

    V4L2应用程序框架 V4L2较V4L有较大的改动,并已成为2.6的标准接口,函盖video\dvb\FM...,多数驱动都在向V4l2迁移.更好地了解V4L2先从应用入手,然后再深入到内核中结合物理 ...

  3. 深入理解java:2. 多线程机制

    引言 很多人都对其中的一些概念不够明确,如同步.并发等等,让我们先理清一些概念,以免产生误会. 多线程:指的是这个程序(一个进程)运行时,产生了不止一个线程. 并行与并发: 并行:多个cpu实例或者多 ...

  4. 第9周总结&实验报告7

    完成火车站售票程序的模拟. 要求:(1)总票数1000张:(2)10个窗口同时开始卖票:(3)卖票过程延时1秒钟:(4)不能出现一票多卖或卖出负数号票的情况.一:实验代码 package first; ...

  5. QML - 实现Gstreamer投屏 投屏画面遮挡

    1.     背景介绍 中控端运行的操作系统是Android,中控软件主要功能有导航.收音机.媒体(音乐).蓝牙(连接).手机互联.行车辅助和系统设置等. 仪表端运行的操作系统是Linux,仪表软件主 ...

  6. 08: mysql主从原理

    1.1 mysql主从同步   参考博客:https://www.cnblogs.com/kevingrace/p/6256603.html 1.mysql主从同步(复制)概念 1. 将Mysql某一 ...

  7. selenium 教程

    selenium 本身是一套web自动化测试工具,但其经常被用于爬虫,解决一些复杂爬虫的问题. selenium 用于爬虫时,相当于模拟人操作浏览器. 浏览器驱动 使用 selenium 需要先安装 ...

  8. 禁止input输入框历史记录

    <input type="text" autocomplete="off" />

  9. R语言模型选择之精度准则与最大值法问题

    在模型选择中我们一般用caret包train函数建立模型,并对模型进行评判 方法1: ) tr_control<-trainControl(method = ) # 创建随机森林模型 model ...

  10. JS中对象的定义及相关操作

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...