模板库

算法库

reverse 字符串,数组翻转

string s = "12345";
int a[] = {1, 2, 3, 4, 5};
reverse(s.begin(), s.end());
s="54321";
reverse(a, a + 5);
//a{5,4,3,2,1};

rotate 将区间内的元素旋转

vector<int> v{2, 4, 2, 0, 5, 10, 7, 3, 7, 1};
sort 0 1 2 2 3 4 5 7 7 10  
//简单地旋转到左侧 1 2 2 3 4 5 7 7 10 0
rotate(v.begin(), v.begin() + 1, v.end());
//简单地旋转到右侧  0 1 2 2 3 4 5 7 7 10
rotate(v.rbegin(), v.rbegin() + 1, v.rend());

is_sorted( begin(digits), end(digits)) 是否升序

//返回false bool
int digits[] = {3, 1, 4, 1, 5};
is_sorted( begin(digits),  end(digits))

vector<int> v1 {1, 2, 3};
is_sorted(begin(v1),end(v1));

lower_bound 返回指向第一个不小于给定值的元素的迭代器

int a[]={1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6};
vector<int> data = { 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6 };
int lower = lower_bound(data.begin(), data.end(), 4)-data.begin();
int lower2 = lower_bound(a, a+13, 4)-a;

upper_bound 返回指向第一个大于给定值的元素的迭代器

int a[]={1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6};
vector<int> data = { 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6 };
int  upper = upper_bound(data.begin(), data.end(), 4)-data.begin();
int  upper2 = upper_bound(a, a+13, 4)-a;

binary_search 判断一个元素是否在区间内

int a[]={1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6};
vector<int> data = { 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6 };
bool flag = binary_search(a,a+13,1);
bool flag2 = binary_search(data.begin(),data.end(),1);

merge 归并 合并两个已排序的区间

vector<int> v1 = { 1, 1, 2, 3, 3, 3 },v2={ 3, 4, 4, 4, 5, 5, 6};
vector<int> dst;
merge(v1.begin(), v1.end(), v2.begin(), v2.end(), back_inserter(dst));

int a[]={1, 3,5},b[]={2,4,6};
vector<int> v;
merge(a,a+3,b,b+3,back_inserter(v));

set_difference 计算两个集合的差集

vector<int> v1 {1, 2, 5, 5, 5, 9};
vector<int> v2 {2, 5, 7};
vector<int> diff;
set_difference(v1.begin(), v1.end(), v2.begin(), 
               v2.end(), inserter(diff, diff.begin()));

set_intersection 计算两个集合的交集

vector<int> v1{1,2,3,4,5,6,7,8};
vector<int> v2{5,7,9,10};
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end());
vector<int> v_intersection;
set_intersection(v1.begin(), v1.end(),
                 v2.begin(), v2.end(),back_inserter(v_intersection));

max_element 返回区间内的最大元素

vector<int> v{ 3, 1, -14, 1, 5, 9 };
int a[]={1,2,3,4,5,7};
vector<int>::iterator result;
result = max_element(v.begin(), v.end());
int x=*max_element(a, a+6);

min_element 返回区间内的最小元素

vector<int> v{ 3, 1, -14, 1, 5, 9 };
int a[]={1,2,3,4,5,7};
vector<int>::iterator result;
result = min_element(v.begin(), v.end());
int x=*min_element(a, a+6);

is_permutation 判断一个序列是否为另一个序列的排列组合

vector<int> v1{1, 2, 3, 4, 5};
vector<int> v2{3, 5, 4, 1, 2};
bool flag=is_permutation(v1.begin(), v1.end(), v2.begin())

next_permutation 按字典顺序产生区间内元素下一个较大的排列组合

string s = "aba";
sort(s.begin(), s.end());
do {
    cout << s << '\n';
} while(next_permutation(s.begin(), s.end()));

prev_permutation 按字典顺序产生区间内元素下一个较小的排列组合

string s = "aba";
sort(s.begin(), s.end(),greater<char>());
do {
    cout << s << '\n';
} while(prev_permutation(s.begin(), s.end()));

数值库

abs labs llabs 计算整数值的绝对值( |x| )
fabs 浮点值的绝对值( |x| ) 
fmod fmodf fmodl 浮点除法运算的余数 
exp expf expl返回 e 的给定次幂( ex )
exp2 exp2 fexp2l 返回 2 的给定次幂( 2x )
expm1 expm1f expm1l 返回 e 的给定次幂减一( ex-1 )
log logf logl 计算自然(底 e )对数( ln(x) )
log10 log10f log10l 计算常用(底 10 )对数( log10(x) )
log2 log2f log2l 给定数的 2 为底的对数( log2(x) )
log1p log1pf log1pl 给定数的自然(底 e )对数加 1 ( ln(1+x) )
pow powf powl 求某数的给定次幂( xy )
sqrt sqrtf sqrtl 计算平方根( √x )
cbrt cbrtf cbrtl 计算立方根( 3√x )
hypot hypotf hypotl 计算二个给定数平方和的平方根(√x2+y2) 
sin sinf sinl 计算正弦( sin(x) )
cos cosf cosl 计算余弦( cos(x) )
tan tanf tanl 计算正切( tan(x) )
asin asinf asinl 计算弧(反)正弦( arcsin(x) )
acos acosf acosl 计算弧(反)余弦( arccos(x) )
atan atanf atanl 计算弧(反)正切( arctan(x) )
atan2 atan2f atan2l 弧(反)正切,用符号确定象限

string库

#include <string>

    string ss = "about you", s;
    int index, count,n;
    char ch;
    //位置都是对应下标表示
    //首字母
    char begin = ss.front();
    //尾字母
    char end = ss.back();
    cout << begin << " " << end << endl;
    //判空
    ss.empty();
    //返回字符串长度
    ss.size();
    //清空字符串
    ss.clear();
    //插入字符
    //在位置 index 插入 count 个字符 ch 的副本。
    index = 0, count = 3;
    ch = 'x';
    ss.insert(index, count, ch);
    cout << ss << endl;
    //在指定位置插入字符串s
    s = "test";
    ss.insert(1, s);
    cout << ss << endl;
//    在位置 index 插入范围 [s, s+count) 中的字符。范围能含有空字符。
    s = "abc";
    //2代表个数
    count = 2;
    ss.insert(0, s, 1, 2);
    cout << ss << endl;

    //erase
    s = "This is an example";
    cout << s << '\n';
// 擦除 "This "
    s.erase(0, 5);
    cout << s << '\n';
// 擦除 ' '
    s.erase(std::find(s.begin(), s.end(), ' '));
    cout << s << '\n';
// 从 ' ' 到字符串尾裁剪
    s.erase(s.find(' '));
    std::cout << s << '\n';
    // push_back  后附字符到结尾
    s.push_back('a');
    //pop_back 移除末尾字符
    s.pop_back();

/*    str   -   要比较的另一 string
    s   -   指向要比较的字符串的指针
    count1  -   此 string 要比较的字符数
    pos1  -   此 string 中要比较的首字符的位置
    count2  -   给定字符串要比较的字符数
    pos2  -   给定字符串的要比较的首字符位置*/
    int compare( size_type pos1, size_type count1, const basic_string& str,
                size_type pos2, size_type count2 )
    s.compare(0,2,"ss",0,2);
//    int compare( size_type pos1, size_type count1, const CharT* s, size_type count2 )
    s.compare(0,2,"ss",2);
    // find 于字符串中寻找字符
    //rfind 寻找子串的最后一次出现
    //size_type find( const CharT* s, size_type pos, size_type count )
    s = "This is a string";

    // 从 string 开始搜索
    n = s.find("is");

    // 从位置 5 开始搜索
    n = s.find("is", 5);

    // 寻找单个字符
    n = s.find('a');
    if (n == string::npos) {
        std::cout << "not found\n";
    } else {
        //找到那个位置到结束,包括找到那个位置
        std::cout << "found: " << s.substr(n) << '\n';
    }

   /* pos   -   将被替换的子串起始位置
    count   -   将被替换的子串长度
    first, last   -   将被替换的字符范围
    str   -   用于替换的 string
    pos2  -   用于替换的子串起始位置
    count2  -   用于替换的字符数
    cstr  -   指向用于替换的字符串的指针
    ch  -   用于替换的字符值
    first2, last2   -   用于替换的字符范围*/
    string str("The quick brown fox jumps over the lazy dog.");
    str.replace(10, 5, "red");
    str.replace(str.begin(), str.begin() + 3, 1, 'A');

    std::cout << str << '\n';
  /*  pos   -   要包含的首个字符的位置
    count   -   子串的长度*/
    std::string a = "0123456789abcdefghij";

    // count 为 npos ,返回 [pos, size())
    std::string sub1 = a.substr(10);
    std::cout << sub1 << '\n';
    //abcdefghij
    // pos 和 pos+count 都在边界内,返回 [pos, pos+count)
    std::string sub2 = a.substr(5, 3);
    //567
    std::cout << sub2 << '\n';

容器库

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <deque>
vector<int> v, v2[5];
vector<pair<int, int> > ans;
map<string, int> m;
multiset<int> mus;
multimap<string, int> mum;
set<int> set;
stack<int> st;
queue<int> qu;
priority_queue<int> pq;
priority_queue<int, vector<int>, greater<int> > q2;
set<int>::iterator it;
set<int>::reverse_iterator rit;


set
唯一键的集合,按照键排序
map
键值对的集合,按照键排序,键是唯一的
multiset
键的集合,按照键排序
multimap
键值对的集合,按照键排序
stack
堆栈适配器(LIFO)
queue
改写容器来提供队列(FIFO数据结构)
priority_queue
改写容器来提供优先级队列

vector
a.assign(b.begin(), b.begin()+3); //b为向量,将b的0~2个元素构成的向量赋给a
a.assign(4,2); //是a只含4个元素,且每个元素为2
front 访问第一个元素
back 访问最后一个元素
迭代器 begin() end()
反向迭代器 rbegin() rend();
empty 检查容器是否为空
size 返回容纳的元素数
max_size 返回可容纳的最大元素数
clear 清除内容
insert 插入元素
erase 擦除元素
push_back 将元素添加到容器末尾
pop_back 移除末元素

map,multimap
迭代器 begin() end()
反向迭代器 rbegin() rend();
empty 检查容器是否为空
size 返回容纳的元素数
max_size 返回可容纳的最大元素数
clear 清除内容
insert 插入元素
erase 擦除元素
count 返回匹配特定键的元素数量
find 寻找带有特定键的元素
lower_bound 返回指向首个不小于给定键的元素的迭代器
upper_bound 返回指向首个大于给定键的元素的迭代器

set,multiset
迭代器 begin() end()
反向迭代器 rbegin() rend();
empty 检查容器是否为空
size 返回容纳的元素数
max_size 返回可容纳的最大元素数
clear 清除内容
insert 插入元素
erase 擦除元素
count 返回匹配特定键的元素数量
find 寻找带有特定键的元素
lower_bound 返回指向首个不小于给定键的元素的迭代器
upper_bound 返回指向首个大于给定键的元素的迭代器

stack
top 访问栈顶元素
empty 检查容器是否为空
size 返回容纳的元素数
push 向栈顶插入元素
pop 删除栈顶的元素

queue
front 访问第一个元素
back 访问最后一个元素
empty 检查容器是否为空
size 返回容纳的元素数
push 向栈顶插入元素
pop 删除栈顶的元素

priority_queue  默认是从大大小,栈顶为最大值
top 访问栈顶元素
empty 检查容器是否为空
size 返回容纳的元素数
push 向栈顶插入元素
pop 删除栈顶的元素

deque
front 访问第一个元素
back 访问最后一个元素
迭代器 begin() end()
反向迭代器 rbegin() rend();
empty 检查容器是否为空
size 返回容纳的元素数
max_size 返回可容纳的最大元素数
clear 清除内容
insert 插入元素
erase 擦除元素
push_back 将元素添加到容器末尾
pop_back 移除末元素
push_front 插入元素到容器起始
pop_front 移除首元素

*it是值
it->ff,it->ss;

几何

n条直线最多分平面问题

题目大致如:n条直线,最多可以把平面分为多少个区域。
  可能你以前就见过这题目,这充其量是一道初中的思考题。
  但一个类型的题目还是从简单的入手,才容易发现规律。
  当有n-1条直线时,平面最多被分成了f(n-1)个区域。
  则第n条直线要是切成的区域数最多,就必须与每条直线相交且不能有同一交点。
  这样就会得到n-1个交点。这些交点将第n条直线分为2条射线和n-2条线断。
  而每条射线和线断将以有的区域一分为二。这样就多出了2+(n-2)个区域。

     故:f(n)=f(n-1)+n

                  =f(n-2)+(n-1)+n

                  ……

                  =f(1)+1+2+……+n

                  =n(n+1)/2+1

折线分平面(hdu2050)

根据直线分平面可知,由交点决定了射线和线段的条数,进而决定了新增的区域数。
  当n-1条折线时,区域数为f(n-1)。为了使增加的区域最多,则折线的两边的线段要和n-1条折线的边,
  即2*(n-1)条线段相交。那么新增的线段数为4*(n-1),射线数为2。
  但要注意的是,折线本身相邻的两线段只能增加一个区域。

   故:f(n)=f(n-1)+4(n-1)+2-1

                  =f(n-1)+4(n-1)+1

                 =f(n-2)+4(n-2)+4(n-1)+2

                 ……

                 =f(1)+4+4*2+……+4(n-1)+(n-1)   

                 =2n^2-n+1

封闭曲线分平面问题

题目大致如设有n条封闭曲线画在平面上,而任何两条封闭曲线恰好相交于两点,
且任何三条封闭曲线不相交于同一点,问这些封闭曲线把平面分割成的区域个数。
    当n-1个圆时,区域数为f(n-1).那么第n个圆就必须与前n-1个圆相交,
  则第n个圆被分为2(n-1)段线段,增加了2(n-1)个区域。
      故
                f(n)=f(n-1)+2(n-1)     

            =f(1)+2+4+……+2(n-1)

            =n^2-n+2

平面分割空间问题(hdu1290)

由二维的分割问题可知,平面分割与线之间的交点有关,即交点决定射线和线段的条数,从而决定新增的区域数。
试想在三维中则是否与平面的交线有关呢?当有n-1个平面时,分割的空间数为f(n-1)。
要有最多的空间数,则第n个平面需与前n-1个平面相交,且不能有共同的交线。
即最多有n-1 条交线。而这n-1条交线把第n个平面最多分割成g(n-1)个区域。
(g(n)为(1)中的直线分平面的个数)此平面将原有的空间一分为二,则最多增加g(n-1)个空间。



    故:f=f(n-1)+g(n-1)  
          g(n)=n(n+1)/2+1

              =f(n-2)+g(n-2)+g(n-1)

              ……

              =f(1)+g(1)+g(2)+……+g(n-1)

              =2+(1*2+2*3+3*4+……+(n-1)n)/2+(n-1)

              =(1+2^2+3^2+4^2+……+n^2-1-2-3-……-n )/2+n+1

              =(n^3+5n)/6+1

用N个三角形最多可以把平面分成几个区域

a[i]=a[i-1]+6*(i-1)