位运算
位运算是一种对二进制位进行操作的运算符,位运算符包括按位与、按位或、按位异或、按位取反、左移、右移等。
-
(AND)与
&
: 0&0 = 0, 0&1 = 0, 1&0 = 0, 1&1 = 1 -
(OR)或
|
:0|0 = 0, 0|1 = 1, 1|0 = 1, 1|1 = 1 -
(NOT)异或
^
: 0^0 = 0, 0^1 = 1, 1^0 = 1, 1^1 = 0 -
(XOR)取反
~
: ~0 = 1, ~1 = 0 -
左移
<<
:a<<b 等价于 a * 2^b -
右移
>>
:a>>b 等价于 a / 2^b
常规操作:
1.求x的第k位数字:x >> k & 1
2.返回x的最后一位1:lowbit(x) = x & -x
计算机里面-a
的原理是:取反加一,即~a + 1
,因此lowbit(a)
的原理是:a & -a
,即a
的二进制表示中最右边的1的位置。
#include <iostream>
using namespace std;
int main()
{
int a = 13;//1101
cout << (a >> 2 & 1) << endl; //1
int b = -a;
int c = (~a + 1);
cout << b << " " << c << endl;//13 13
cout << lowbit(a) << endl; //1
return 0;
}
常用库函数
reverse 翻转
左开右闭
翻转一个vector:reverse(a.begin(), a.end())
翻转一个数组,元素存放在下标1~n:reverse(a + 1, a+1+n)
#include <iostream>
#include <algorithm>
#include <vectr>
using namespace std;
int main()
{
//vector
vector<int> a = {1,2,3,4,5};
reverse(a.begin(), a.end()); //翻转
for(int i : a) cout << i << " ";
cout << endl;
//数组
int b[5] = {1,2,3,4,5};
reverse(b, b + 5); //翻转
for(int i : b) cout << i << " ";
cout << endl;
return 0;
}
unique 去重
返回去重之后的尾迭代器(或指针),仍然为前闭后开,即这个迭代器是去重之后末素的下一位置。该函数常用于离散化,利用迭代器(或指针)的减法,可计算出去重后的元素个数。
把一个vector去重:
int m = unique(a.begin(). a.end())-a.begin()
把一个数组去重,元素存放在下标1~n:
int m = unique(a + 1, a +1+n)-(a+1)
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int a[] = {1, 1, 2, 2, 3, 3, 4};
int m = unique(a, a + 7) - a;
cout << m << endl;//4
for(int i = 0;i < m; i ++) cout << a[i] << ' ';//1 2 3 4
cout << endl;
vector<int> b = {1, 1, 2, 2, 3, 3, 4};
int n = unique(b.begin(), b.end()) - b.begin();
cout << n << endl;//4
for(int i = 0;i < n; i ++) cout << b[i] << ' ';//1 2 3 4
cout << endl;
/*
a.erase(unique(a.begin(), a.end()), a.end()); //利用erase函数去重)
for(auto x: a) cout << x <<' ';//1 2 3 4
*/
return 0;
}
random_shuffle 随机打乱
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
using namespace std;
int main()
{
vector<int> a = {1, 2, 3, 4, 5};
srand(time(0)); //设置随机种子
random_shuffle(a.begin(), a.end()); //随机打乱
for(int i : a) cout << i << " ";
cout << endl;
return 0;
}
sort 排序
从小到大:sort(a.begin(), a.end())
从大到小:sort(a.begin(), a.end(), greater<int>())
自定义排序:sort(a.begin(), a.end(), cmp)
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool cmp(int a, int b) { return a > b; } //降序
int main()
{
vector<int> a = {5, 3, 1, 4, 2};
sort(a.begin(), a.end()); //升序
for(int i : a) cout << i << " ";
cout << endl;
sort(a.begin(), a.end(), cmp); //降序
//else
//sort(a.begin(), a.end(), greater<int>());
for(int i : a) cout << i << " ";
cout << endl;
return 0;
}
结构体排序:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct Rec
{
int x,y;
/*重载小于号
bool operator< (const Rec& t) const
{
return x < t.x;
}*/
}a[5];
bool cmp(Rec a, Rec b)
{
return a.x < b.x;
}
int main()
{[
for(int i = 0; i < 5; i ++)
{
a[i].x = -i;
a[i].y = i;
}
for(int i = 0; i < 5; i ++) printf("%d %d\n", a[i].x, a[i].y);
cout << endl;
sort(a, a + 5, cmp);
for(int i = 0; i < 5; i ++) printf("%d %d\n", a[i].x, a[i].y);
cout << endl;
return 0;
}
lower_bound / upper_bound 二分查找
lower bound
的第三个参数传入一个元素 x ,在两个迭代器(指针)指定的部分上执行二分查找,返回指向第一个大于等于 x的元素的位置的迭代器(指针)。
upper bound
的用法和 lower _ bound
大致相同,唯一的区别是查找第一个大于 x的元素。当然,两个迭代器(指针)指定的部分应该是提前排好序的。
在有序 int 数组(元素存放在下标1~ n )中查找大于等于 x 的最小整数的下标:int |= lower bound ( a +1, a +1+ n .. x )- a
在有序 vector < int >中查找小于等于 x 的最大整数(假设一定存在): int y =*-- upper _ bound ( a . begin (), a . end (). x )
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
int a[] = {1, 2, 4, 5, 6};
int *p = lower_bound(a, a + 5, 3); //返回指向第一个大于等于3的元素的位置的指针
cout << *p << endl; //4
int t = lower_bound(a, a + 5, 7) - a; //返回指向最后一个元素的下一个位置的指针
cout << t << endl; //5
vector<int> b = {1, 2, 4, 5, 6};
int t = upper_bound(b.begin(), b.end(), 3); //返回指向第一个大于3的元素的位置的指针
cout << a[t] << endl; //4
return 0;
}