C++学习笔记
1.参数
给函数设置参数时可以的话最好把参数设置为要修改的值的引用,而不是设置为返回值,这样可以避免不必要的复制。(当然前提是你希望该值被修改,如果不应该被修改就不要用引用参数)
//例如
void fill_random_int(vector<int>& v,int cnt){
v.clear();
for(int i = 0; i < cnt;i++)
v.push_back(rand());
}
//和
vector<int> fill_random_int(int cnt){
vector<int> v;;
for(int i = 0; i < cnt;i++){
v.push_back(rand());
}
return v;
}
//下面的函数在返回vector变量时,实际上是把函数体里面的v的所有值都复制给调用者,浪费时间。
2.find函数用法
用途:查找数组或vector中首次出现的元素的下标
#include <algorithm>//find函数所在头文件
#include <iostream>
#include <set>
#include <string>
#include <vector>
using namespace std;
int main(int argc, const char* argv[]) {
vector<int> a = {1, 2, 3};
int b[7] = {1, 2, 3, 4, 3, 4, 5};
string s = "abcdefghijklmnopqrst";
set<int> c = {1, 2, 3, 4, 5};
vector<int>::iterator p1; //注意在对vector使用find函数时的返回类型
p1 = find(a.begin(), a.end(), 3);
int* p2; //注意对数组使用find函数时的返回类型
p2 = find(b + 7, b + 10, 3);
size_t p3 = s.find('a'); //注意string类型有单独的find函数及其返回类型
set<int>::iterator p4; //注意set类型有单独的find函数及其返回类型(无法查位置)
p4 = c.find(3);
cout << find(a.begin(), a.end(), 3) - a.begin() << endl; //注意上面写的返回值一般不用来输出,下面两个将输出long long类型的下标(均从0开始)
cout << find(b + 7, b + 10, 3) - b << endl;
cout << p3 << endl;
return 0;
}
3. 寻找最大值/max_element
#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <vector>
using namespace std;
int main(int argc, const char* argv[]) {
vector<int> a = {1, 2, 3, 4}; //可应用于多种数据类型
int b[5] = {3, 55, 7, 5, 2};
set<int> c = {1, 2, 4, 8};
vector<string> d = {"saf", "afsdf", "werqio", "aaaaaaa", "z"}; //注意string类型的比较方法,挨个元素比较,"z"最大
cout << *max_element(d.begin(), d.end()) << endl; //输出最大值
cout << *max_element(c.begin(), c.end()) << endl;
cout << *max_element(b, b + 5) << endl;
cout << *max_element(a.begin(), a.end()) << endl;
cout << max_element(d.begin(), d.end()) - d.begin() << endl; //输出最大值下标
// cout << max_element(c.begin(), c.end()) - c.begin() << endl;对set来说还是不行,因为set无序
cout << max_element(b, b + 5) - b << endl;
cout << max_element(a.begin(), a.end()) - a.begin() << endl;
return 0;
}
输出
2
10
0
4. 求交并集
set_union与set_intersection用法
#include <algorithm>
#include <iostream>
#include <iterator>
#include <set>
#include <vector>
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x.begin())
using namespace std;
vector<int> intersection1(vector<int>& nums1, vector<int>& nums2) {
vector<int> res1, res2;
set<int> s1(ALL(nums1)), s2(ALL(nums2));
set_intersection(ALL(s1), ALL(s2), INS(res1)); //求交集
set_union(ALL(s1), ALL(s2), ALL(res2)); //求并集
return res1, res2;
}
vector<int> intersection2(vector<int>& nums1, vector<int>& nums2) {
vector<int> res1, res2;
sort(ALL(nums1));//set_union()和set_intersection()并不是set的专用方法,而是std里面,故也可以直接对vector使用
sort(ALL(nums2));//传递的容器必须是排序的,set 容器中元素默认是排序的,而 vector 需要调用 sort 函数进行排序
set_intersection(ALL(nums1), ALL(nums2), INS(res1)); //求交集
set_union(ALL(nums1), ALL(nums2), ALL(res2)); //求并集
return res1, res2;
}
5. compare函数
注意string1.compare(string2)函数的返回值,当二者相等时返回0,不等时返回-1
6. 优先队列自定义类型的优先级问题
对于自定义类型(一般指结构体),要么在结构体内部重载运算符,要么在结构体外面定义仿函数【struct cmp内部重载"()"运算符】,样例如下:
注意:
如果用less的话,需要重载"<",并且在返回值中用">“才能实现从小到大排列,
如果用greater的话,需要重载”>",在返回值中依然是用">"才能实现从小到大排列。
typedef struct STRUCT {
int dis;
int index;
friend bool operator<(const STRUCT& a, const STRUCT& b) {
return a.dis > b.dis;
}
} node;
priority_queue<node, vector<node>, less<node>> q;//实现了按dis从小到大排列
实现"个位数越大优先级越小"
typedef struct STRUCT {
int num;
int index;
} node;
struct cmp { //仿函数
bool operator()(const node& a, const node& b) const {
if(a.num == b.num) {
return a.index > b.index;
}
return a.num < b.num;//"<"为从大到小排列,">"为从小到大排列
}
};
struct node{
int x;
int y;
friend bool operator < (node a,node b)
{
if(a.x==b.x)
return a.y<b.y;
return a.x>b.x;
}
};
7.map排序问题
注意map中默认是按Key从小到大排列的(即在定义map时,第三个参数默认是less),也可通过定义仿函数作为第三个参数传给map定义的方式对Key进行其他方式的排序(如原本Key为string类型,则其默认为字典序从小到大排序,可通过写仿函数然后传参的方式使其按字符串长度排序)。注意map无法使用sort函数(map为非线性容器),若要按Value进行排序,只能把将数据从map中取出,具体操作在这里
8. 位运算判断一个整数是否为2的幂
先放结论:
bool is_power_of_two(int n) {
return (n != 0) && ((n & -n) == n);
}
证明:对于以补码形式存储的整数来说,- n = ~ n + 1,该运算的一个重要性质为:n 与 - n 的二进制形式中最后一个1及之后的所有0相同,而之前的所有位均为相反数,如:
对于12来说,他的二进制表示为01100,-12的二进制表示为10100,计算过程为:12=10011,可以看到,12中最后的一连串的0在反转后全部变为1,12+1=10100,那么在加完1之后,这些反转后的1又都会变成0,而前一位优惠变成1,而更前面的则相当于只进行了翻转运算,而2的幂的二进制表示的最重要的特点即为整个1-0串中只有一个1,故成立。
而要注意的是,0也满足上述变换,故需单独考虑
9.关于快速排序
快速排序首先确定一个基准值(一般选择首或尾),希望能使得小于该基准值的都在前面,大于该基准值的都在后面,这样再把基准值放到两区域交界处,基准值就归位(处于正确位置)了,过程则是利用双指针从两头向中间扫描,右边遇到小于基准值的停一停,左边遇到大于基准值的停一停,然后二者交换,一直到两指针相遇,由于我们选择让右指针先移动,故最后左指针所在位置的值arr[i]为小于基准值的最右面的一个位置,记其为mid,将其与基准值所在位置进行值交换,第一轮就结束了。之后便可以用递归的方式来对左半边和右半边分别快排。
问题1:若数据有序性很高,或者极端情况下数据完全有序,那么就会导致每轮结束后,下一轮的两边长度分别为1和n-1,最终形成与冒泡排序一样的局面,时间复杂度为O(N^2)
int quick_sort(int* arr, int l, int r) {
int i = l, j = r, temp = arr[l];
while(i < j) {
while(i < j && arr[j] > temp) {
j--;
}
while(i < j && arr[i] <= temp) {
i++;
}
if(i < j) {
swap(arr[i], arr[j]);
}
}
swap(arr[l], arr[i]);
return i;
}
void Quick(int* arr, int l, int r) {
int mid;
if(l < r) {
mid = quick_sort(arr, l, r);
Quick(arr, l, mid - 1);
Quick(arr, mid + 1, r);
}
}
解决方法1:每次随机从 l ~ r 之间随机选择一个下标,以其代表的值为基准值,可以有效防止每次都得到最差结果。
void Quick(int* arr, int l, int r) {
if(l < r) {
int i = l, j = r, temp = rand() % (r - l + 1) + l;
swap(arr[l], arr[temp]);
while(i < j) {
while(i < j && arr[j] > arr[l]) {
j--;
}
while(i < j && arr[i] <= arr[l]) {
i++;
}
if(i < j) {
swap(arr[i], arr[j]);
}
}
swap(arr[l], arr[i]);
Quick(arr, l, i - 1);
Quick(arr, i + 1, r);
}
}
解决方法2:每次都选中间为基准,因为设计的数据要么有序(以首尾为基准的基本凉凉),要么无序,而无序且数据很大且能使每次以中间为基准的选法达到最差的情况,这种可能就很小了。
void Quick(int* arr, int l, int r) {
int i = l, j = r, temp = arr[(l + r) >> 1];
while(i <= j) {
while(arr[i] < temp) {
i++;
}
while(arr[j] > temp) {
j--;
}
if(i < j) {
int t = arr[i];
arr[i++] = arr[j];
arr[j--] = t;
}
}
if(l < j) {
Quick(arr, l, j);
}
if(r > i) {
Quick(arr, i, r);
}
}0
10.树状数组
本质:是数组而不是树
用途:单点修改与区间求和,区间修改与单点取值(线段树都可以实现,不过显得大材小用)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eyBp9IZZ-1595066141487)(./assets/树状数组.png)]
树状数组利用二进制的思想,以上图为例,红色代表树状数组bit[],黑色代表原生数组arr[],则可直观看出
bit[1]=arr[1];
bit[2]=arr[1]+arr[2];
…
bit[6]=arr[5]+arr[6];
…
bit[12]=arr[9]+arr[10]+arr[11]+arr[12];
…
bit[14]=arr[13]+arr[14]
…
简单找规律(查资料)后发现,C[i] = A[i - 2k+1] + A[i - 2k+2] + … + A[i]; //k为i的二进制中从最低位到高位连续零的长度,即i的二进制表示中最后一位1及后面所有的0组成的数。
那么2k该怎么求呢?
参考本文第八个小知识点,可知2k即为i中最小的2的幂,而该知识点中判断的方法正好可以用来获得i的二进制表示中最后一位1及后面所有的0组成的数,即(i&(-i)).
//需要先构造lowbit函数或宏
//宏
#define lowbit(x) (x&(-x))
//函数
int lowbit(int x){
return (x&(-x));
}
单点修改与区间求和
构造树状数组:
arr[i] 包含于 bit[i + 2k]、bit[(i + 2k) + 2k]…
所需空间为线性,bit[max_num]即可(构造全局变量)
随数据的输入直接构造即可(相当于原数据均为0,然后每次单点增加arr[i]大小的数据,因此,单点修改有着与之一样的操作):
void update(int index,int delta,int num){
while(index<=num){
bit[index]+=delta;
index+=lowbit(index);
}
}
...
for(int i=1;i<=num;i++){
cin>>arr[i];
update(i,arr[i],num);
}
区间求和:
int query(int index,int num){
int ans=0;
while(index>0){
ans+=bit[index];
index-=lowbit(index);
}
return ans;
}
上述代码求解的是 $ \sum_{i=1}^{index} $(arr[i]),要想求解区间x~y范围内的数据和,只需query(y)-query(x-1).
区间修改与单点取值
与单点修改不同,在区间修改的过程中,若是按上述过程对区间中的数据分别修改,则完全体现不出树状数组的优势,因此这里引入差分的概念。
核心:差分!!!
对于序列a1,a2,a3…an,对它进行差分就变成了a1 ,a2-a1 ,a3-a2…,an-an-1,差分后的序列的前i项和
sum=a1+(a2-a1)+(a3-a2)+…+(ai-1-ai-2)+(ai-ai-1)=ai
即从1到 i - 1 项都被消掉了,最后只剩下了ai,得出结论:差分后序列的前 i 项和等于差分前第 i 个元素的值,利用此性质再结合上面的query()函数,则可以快速进行单点取值。
那么差分在区间修改过程中有什么奇妙的应用呢?
由上述结论可以推出当原数组的连续区间[L,R]被统一修改时,其差分数组只需要修改index=L和index=R+1的两个数据,原因如下:
原因如下
-
区间[L,R]内每个元素都加上了相同的值,所以相对差距并没有改变,所以[L+1,R]的差分值并没有改变,但是这个区间的两头却会发生改变;
-
第L个元素加上了x,但第L-1个元素没有加x,所以第L个元素的差分结果就会从原来的(aL-aL-1)变成了现在的(aL-aL-1+x),增加了x;
-
同理尾部第R个元素加上了x,但是第R+1个元素没有加x,所以第R+1个元素的查分结果就从原来的(aR+1-aR)变成了现在的(aR-aR-1-x),减少了x.
void update(int index,int delta,int num){ while(index<=num){ bit[index]+=delta; index+=lowbit(index); } } int last=0,cur; for(int i = 1; i <= num; i++) { cin>>cur; update(i, cur - last, n); last = cur; }
11. 快速读入(整型)
因为getchar()最快,所以:
int read() {
int f = 1, ans = 0;//f为正负号标记,ans一定要初始化为0,因为后面要累加
char c = getchar();
while(c < '0' || c > '9') {
if('-' == c) {
f = -1;
}
c = getchar();
}
while(c >= '0' && c <= '9') {
ans = ans * 10 + c - '0';
c = getchar();
}
return ans * f;
}
12. 单调队列
顾名思义单调队列就是单调递增或单调递减的队列,可通过STL里面的deque实现,也可以通过数组加左右指针实现,前者较慢,后者较快。通常用来计算固定大小窗口里面的最大值、最小值。
Eg.1
题面:有一个长为 nn 的序列 aa,以及一个大小为 kk 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。输入格式
输入一共有两行,第一行有两个正整数 n, k, 第二行 n 个整数,表示序列 arr
输出共两行,第一行为每次窗口滑动的最小值, 第二行为每次窗口滑动的最大值.
1 <= k <= n <= 106, arr[i] ∈ \in ∈ [2-31,231).
例如:
The array is arr = [1,3,−1,−3,5,3,6,7], and k = 3。
输入:
8 3
1 3 -1 -3 5 3 6 7
输出:
-1 -3 -3 -3 3 3
3 3 5 5 6 7
解析:典型的求滑动固定窗口最大、最小值的问题,直接套单调队列模板,注意单调队列一般存的都是下标。
deque实现
#include <cstdio>
#include <iostream>
#include <queue> //deque所在头文件
using namespace std;
const int max_num = 1e6 + 10;
int arr[max_num];
deque<int> q;
int read(); //快速读入
int main() {
int n, k;
n = read();
k = read();
for(int i = 0; i < n; i++) {
arr[i] = read();
}
long long ans = 0;
for(int i = 0; i < n; i++) { //先算最小值,用单增队列
while(!q.empty() && arr[q.back()] > arr[i]) {
q.pop_back();
}
q.push_back(i);
if(i >= k) { //完全形成一个窗口,接下来开始滑动
while(q.front() <= i - k) {
q.pop_front();
}
printf("%d ", arr[q.front()]);
}
}
printf("\n");
q.clear(); //清空队列
for(int i = 0; i < n; i++) { //再算最大值
while(!q.empty() && arr[q.back()] < arr[i]) {
q.pop_back();
}
q.push_back(i);
if(i >= k) { //完全形成一个窗口,接下来开始滑动
while(q.front() <= i - k) {
q.pop_front();
}
printf("%d ", arr[q.front()]);
}
}
return 0;
}
int read() {
int f = 1, ans = 0;
char c = getchar();
while(c < '0' || c > '9') {
if('-' == c) {
f = -1;
}
c = getchar();
}
while(c >= '0' && c <= '9') {
ans = ans * 10 + c - '0';
c = getchar();
}
return ans * f;
}
数组实现
#include <cstdio>
#include <iostream>
using namespace std;
const int max_num = 1e6 + 10;
int arr[max_num], deq[max_num], l = 1, r = 0; //注意左右指针的实现
int main() {
//这里不再写数据的输入了
for(int i = 0; i < n; i++) {
while(l <= r && arr[deq[r]] > arr[i]) {//要求最大值只需要把'>'换成'<'(加不加'='都无所谓)
//要把刚滑进窗口的数据插入到单调队列里来,先把不合要求的数据删掉,这里用指针移动来代替
r--;
}
deq[++r] = i;
if(i >= k - 1) {
while(deq[l] <= i - k) {
l++;
}
printf("%d", arr[deq[l]]);
}
}
return 0;
}
Eg.2
题目:给定一个n*m的矩阵mat[n][m],对于矩阵中任意的一个位置(i,j),其值为lcm(i,j)***(lcm为i和j的最小公倍数)**,再给定一个k,求该nm的数组中所有k*k的小矩阵中最大值的和。
例如:输入n=3,m=4,k=2
则得到的3*4的矩阵为
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5h1p12rQ-1595066141492)(D:%5CTools%5CType%5CMarkDown%5Cassets%5Cimage-20200718001948042.png)]
然后从[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RpChu8of-1595066141494)(D:%5CTools%5CType%5CMarkDown%5Cassets%5Cimage-20200718002035906.png)]开始,获取所有的2*2的小矩阵中的最大值,然后求和,得到的结果就是2+6+6+6+6+12=38.\
要求: 1 <= n, m <= 5000, 1 <= k <= min{n,m},time<3s
题解:该题可以用滑动窗口或者单调队列来解,不过前者慢且难写,后者快且便于书写,后者还可以分别用deque和数组实现,deque会很慢,数组就很快。不过该题其实容易TLE在创建该数组上,如果使用每一个位置都暴力计算gcd再i*j/gcd(i,j)***【O(n*m*log(n))】***的话,是绝对TLE的,这里使用O(n*m)的方法:
for(inti = 1; i <= n; i++)
for(intj = 1; j <= m; j++)
if(!Gcd[i][j])
for(intk = 1; k * i <= n && k * j <= m; k++)
Gcd[k * i][k * j] = k, A[k * i][k * j] = i * j * k;//这里用了两个数组,一个存gcd, 另一个才是mat数组。
之后便是二维数组上的单调队列。
deque实现(TLE)
#include <cstdio>
#include <iostream>
#include <queue>
using namespace std;
typedef struct {
int x;
int y;
} node;
const int max_num = 5010;
int mat[max_num][max_num];
deque<node> q;
int read();
int main(int argc, const char* argv[]) {
int n, m, k;
n = read();
m = read();
k = read();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(!mat[i][j])
for(int k = 1; k * i <= n && k * j <= m; k++)
mat[k * i][k * j] = k;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
mat[i][j] = i * j / mat[i][j];
long long ans = 0;
for(int i = 1; i <= n - k + 1; i++) {
q.clear();
for(int j = 1; j <= m; j++) {
for(int row = i; row <= i + k - 1; row++) {
while(!q.empty() && mat[q.back().x][q.back().y] < mat[row][j]) {
q.pop_back();
}
q.push_back({row, j});
}
if(j >= k) {
while(q.front().y <= j - k) {
q.pop_front();
}
ans += mat[q.front().x][q.front().y];
}
}
}
printf("%lld", ans);
return 0;
}
int read() {
int f = 1, ans = 0;
char c = getchar();
while(c > '9' || c < '0') {
if('-' == c) {
f = -1;
}
c = getchar();
}
while(c >= '0' && c <= '9') {
ans = ans * 10 + c - '0';
c = getchar();
}
return f * ans;
}
数组实现
#include <algorithm>
#include <cstdio>
#include <time.h>
using namespace std;
typedef long long LL;
#define N 1000010
int n, m, k, A[N][N], B[N][N];
LL ans;
void Handle(int n, int m) {
static int q[N];
for(int i = 1; i <= n; i++) {
int l = 1, r = 0;
for(int j = 1; j < k; j++) {
while(l <= r && A[i][q[r]] <= A[i][j]) {
r--;
}
q[++r] = j;
}
for(int j = k; j <= m; j++) {
while(l <= r && q[l] + k <= j) {
l++;
}
while(l <= r && A[i][q[r]] <= A[i][j]) {
r--;
}
q[++r] = j;
B[j - k + 1][i] = A[i][q[l]]; //转置操作
}
}
}
int main() {
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(!A[i][j])
for(int k = 1; k * i <= n && k * j <= m; k++)
A[k * i][k * j] = k;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
A[i][j] = i * j / A[i][j]; //懂了
Handle(n, m); //先把每一行看成一维数组,以1*k的窗口滑动,记录每个窗口的最大值,并将其转置之后放到B数组里面(即本来应该是竖着的,转成横着的了)
for(int i = 1; i <= m - k + 1; i++)
for(int j = 1; j <= n; j++)
A[i][j] = B[i][j]; //把B数组复制到A数组里面
Handle(m - k + 1, n); //再在A数组里面再来一次单调队列,依然是横着,因为转置过了
for(int i = 1; i <= n - k + 1; i++)
for(int j = 1; j <= m - k + 1; j++)
ans += B[i][j]; //最后加起来就行了
printf("%lld\n", ans);
return 0;
}
13.bitset<template T>
构造函数
bitset<4> bitset1; //无参构造,长度为4,默认每一位为0
bitset<8> bitset2(12); //长度为8,二进制保存,前面用0补充
string s = "100101";
bitset<10> bitset3(s); //长度为10,前面用0补充
char s2[] = "10101";
bitset<13> bitset4(s2); //长度为13,前面用0补充
cout << bitset1 << endl; //0000
cout << bitset2 << endl; //00001100
cout << bitset3 << endl; //0000100101
cout << bitset4 << endl; //0000000010101
注意:
-
构造时,需在<>中表明bitset 的大小(即size)。
-
在进行有参构造时,若参数的二进制表示比bitset的size小,则在前面用0补充(如上);若比bitsize大,参数为整数时取后面部分,参数为字符串时取前面部分(如下)
bitset<2> bitset1(12); //12的二进制为1100(长度为4),但bitset1的size=2,只取后面部分,即00
string s = "100101";
bitset<4> bitset2(s); //s的size=6,而bitset的size=4,只取前面部分,即1001
char s2[] = "11101";
bitset<4> bitset3(s2); //与bitset2同理,只取前面部分,即1110
cout << bitset1 << endl; //00
cout << bitset2 << endl; //1001
cout << bitset3 << endl; //1110
操作符
&(按位与),|(按位或),^(按位异或),~(按位取反),>>(右移若干位,左边补0),<<(左移若干位,右边补0),[](按下标取值)
注意:bitset起始位为0,且为最右端
常用函数
bitset<8> foo ("10011011");
cout << foo.count() << endl; //5 (count函数用来求bitset中1的位数,foo中共有5个1
cout << foo.size() << endl; //8 (size函数用来求bitset的大小,一共有8位
cout << foo.test(0) << endl; //true (test函数用来查下标处的元素是0还是1,并返回false或 true,此处foo[0]为1,返回true
cout << foo.test(2) << endl; //false (同理,foo[2]为0,返回false
cout << foo.any() << endl; //true (any函数检查bitset中是否有1
cout << foo.none() << endl; //false (none函数检查bitset中是否没有1
cout << foo.all() << endl; //false (all函数检查bitset中是全部为1
注意:test函数会对下标越界作出检查,而通过 [] 访问元素却不会经过下标检查,所以,在两种方式通用的情况下,选择test函数更安全一些
cout << foo.flip(2) << endl; //10011111 (flip函数传参数时,将参数所指下标位取反
cout << foo.flip() << endl; //01100000 (flip函数不指定参数时,将bitset每一位全部取反
cout << foo.set() << endl; //11111111 (set函数不指定参数时,将bitset的每一位都置为1
cout << foo.set(3) << endl; //11111111 (set函数只有一个参数时,将参数下标处置为1
cout << foo.set(3,0) << endl; //11110111 (set函数指定两位参数时,将第一参数位的元素置为 第二参数的值,本行对foo的操作相当于foo[3]=0
cout << foo.reset(4) << endl; //11101111 (reset函数传一个参数时将参数下标处置为0
cout << foo.reset() << endl; //00000000 (reset函数不传参数时将bitset的每一位全部置为0
上面的函数也都会检查下标是否越界,如果越界就会抛出异常
类型转换函数
bitset<8> foo ("10011011");
string s = foo.to_string(); //将bitset转换成string类型
unsigned long a = foo.to_ulong(); //将bitset转换成unsigned long类型
unsigned long long b = foo.to_ullong(); //将bitset转换成unsigned long long类型
cout << s << endl; //10011011
cout << a << endl; //155
cout << b << endl; //155
例题
题目链接:Greater and Greater
题解链接:Libra的blog