算法竞赛从入门到进阶
算法竞赛从入门到进阶
1.算法竞赛概述
1.1 C语言中输入输出函数
- putchar()
- getchar
- printf()
- scanf()
- puts()
- gets()
- sscanf()
1.2 输入结束方式
while(scanf("%d %d",&a,&b) != EOF){
}
//等价于
while(~scanf("%d %d",&a,&b)){
//一般使用这种方式
}
1.3 编码技巧
把长字符重新定义成段字符 节省编码时间
typedef long long ll;
long long a;
//变为
ll a;
1.4 最好不要用宏定义 容易出现问题
使用const定义常量 例如
const int MAX=100005;
把宏函数写成普通函数
2.STL和基本数据结构
2.1 容器
顺序式容器 vector list deque queue priority_queue stack等
关联式容器 set multiset map multimap等
2.1.1 vector
动态数组
定义
vector<int> a;
vector<int> a(100);
vector<int> a(100,5);
vector<string> b(a.begin(),a.end());
操作
a.push_back(100);
int size=a.size();
bool isEmpty=a.empty();
count<<a[0]<<endl;
a.insert(a.begin()+i,k); //在第i个元素前面插入k
a.insert(a.end(),10,5); //在尾部插入10个值为5的元素
a.pop_back();
a.erase(a.begin()+i,a.begin()+j);//删除区间[i,j-1]的元素
a.erase(a.begin()+2); //删除第三个元素
a.resize(n);
a.clear();
reverse(a.begin(),a.end());
sort(a.begin(),a.end());
2.1.2 stack
操作
stack<type> s;
s.push(item);
s.top(); //返回栈顶元素 但不会删除
s.pop(); //删除栈顶元素 但不会返回
//一般是先返回在删除 所以先top 在pop
s.size();
s.empty();
2.1.3 queue
操作
queue<type> q;
q.push(item);
q.pop();
q.front(); //返回队首元素但不会删除
q.back();
q.size();
q.empty();
2.1.4 priority_queue
优先队列
在STL中,优先队列是用二叉堆来实现的,优先级最高的先出队。每次的push和pop操作,优先队列都会动态的调整,把优先级最高的元素放在前面。
操作
q.top();//返回优先级最高的元素值 但不删除
q.pop();
q.push(item);
2.1.5 链表 list
STL中的list是双向链表
函数原型:
list<T> lst;//list采用采用模板类实现,对象的默认构造形式:list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。list(n,elem);//构造函数将n个elem拷贝给本身。list(const list &lst);//拷贝构造函数。
功能描述:
- 给list容器进行赋值,以及交换list容器
函数原型:
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);//将n个elem拷贝赋值给本身。list& operator=(const list &lst);//重载等号操作符swap(lst);//将lst与本身的元素互换。
功能描述:
- 对list容器的大小进行操作
函数原型:
-
size();//返回容器中元素的个数 -
empty();//判断容器是否为空 -
resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除。
-
resize(num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。 //如果容器变短,则末尾超出容器长度的元素被删除。
功能描述:
- 对list容器进行数据的插入和删除
函数原型:
- push_back(elem);//在容器尾部加入一个元素
- pop_back();//删除容器中最后一个元素
- push_front(elem);//在容器开头插入一个元素
- pop_front();//从容器开头移除第一个元素
- insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
- insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
- insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
- clear();//移除容器的所有数据
- erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
- erase(pos);//删除pos位置的数据,返回下一个数据的位置。
- remove(elem);//删除容器中所有与elem值匹配的元素。
2.1.6 set
set 就是集合 STL中的set用二叉搜索树实现,集合中的每个元素只出现一次并排好序的。访问元素的时间复杂度是O(nlogn);
操作
set<type> A;
A.insert(item);//插入元素
A.erase(item);//删除元素
A.clear();
A.empty();
A.size();
A.find(k); //返回一个迭代器,指向键值k
A.lower_bound(k);//返回一个迭代器,指向键值不小于k的第一个元素
A.upper_bound();//返回一个迭代器,指向键值大于k的第一个元素
2.1.7 map
简介:
- map中所有元素都是pair
- pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
- 所有元素都会根据元素的键值自动排序
本质:
- map/multimap属于关联式容器,底层结构是用二叉树实现。
优点:
- 可以根据key值快速找到value值
功能描述:
- map容器进行插入数据和删除数据
函数原型:
insert(elem);//在容器中插入元素。clear();//清除所有元素erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(key);//删除容器中值为key的元素。
功能描述:
- 对map容器进行查找数据以及统计数据
函数原型:
find(key);//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();count(key);//统计key的元素个数
学习目标:
- map容器默认排序规则为 按照key值进行 从小到大排序,掌握如何改变排序规则
主要技术点:
- 利用仿函数,可以改变排序规则
示例:
#include <map>
class MyCompare {
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
void test01()
{
//默认从小到大排序
//利用仿函数实现从大到小排序
map<int, int, MyCompare> m;
m.insert(make_pair(1, 10));
m.insert(make_pair(2, 20));
m.insert(make_pair(3, 30));
m.insert(make_pair(4, 40));
m.insert(make_pair(5, 50));
for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key:" << it->first << " value:" << it->second << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
总结:
- 利用仿函数可以指定map容器的排序规则
- 对于自定义数据类型,map必须要指定排序规则,同set容器
2.2 sort()
void sort(RandomAccessItarator first,RandomAccessItarator last); 包括first 但不包括last
void sort(RandomAccessItarator first,RandomAccessItarator last,Compare mycompare); 包括first 但不包括last 自己定义的比较规则
比较规则:less
2.2 next_permutation()
STL提供求下一个排列组合的函数next_permutation() 例如a,b,c三个字符组成的序列,next_permutation()函数能按照字典序返回6个组合 即abc acb......
bool next_permutation(BidrectionalIterator first,BidrectionalIterator last); 包括first 不包括last
bool next_permutation(BidrectionalIterator first,BidrectionalIterator last,Compare mycompare);
有下一种排列组合的话返回true 否则false。
每调用一次,就会把新的排列放到原来的空间里。
复杂度O(n)
一般使用该函数的适合,初始序列一般是一个字典序的最小序列,如果不是,可以调用sort()函数进行排序得到最小序列,再使用该函数。
#include <iostream>
#include<algorithm>
using namespace std;
int a[1001];
int m;
int main()
{
cin.sync_with_stdio(false);
cin.tie(nullptr);
cin>>m;
for (int i = 1; i <= m; i++) a[i]=i;
do{
for (int i = 1; i <= m; i++) cout<<a[i]<<" ";
cout<<endl;
}while(next_permutation(a+1,a+m+1));
return 0;
}
测试结果
3
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
3.搜索技术
搜索使用的算法是BFS和DFS,DFS用递归来实现,BFS用队列来实现。
搜索算法的思想就是暴力法,可以在暴力的过程中进行优化,利用剪枝函数减少搜索空间,提高效率。
3.1 递归和排列
x=x&(x-1) 功能是消除x的二进制数的最后一位1,利用这个操作可以计算出二进制中1的个数。
用num统计1的个数,每次执行x=x&(x-1) 操作后 num++,直到x=0。
本文来自博客园,作者:guoyuxin3,转载请注明原文链接:https://www.cnblogs.com/guoyuxin3/p/15202860.html

浙公网安备 33010602011771号