目录
二分查找函数lower_bound( )和upper_bound( )用法
由算法范围反推算法时间复杂度
一般ACM ,NOI(CSP)或者笔试题的时间限制是1秒或2秒。在这种情况下,C++代码中的操作次数控制在(10^7)为最佳。
下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择:
n≤30,指数级别, dfs+剪枝,状态压缩dp
n ≤100 => O(n3), floyd,dp
n ≤1000 => O(n2),O(n2log(n)),dp,二分n ≤10000 => o(n√n),块状链表
n≤100000 =>O(nlog(n))=>各种sort,线段树、树状数组、set/map、heap、djkstra+heap、spfa、求凸包、求半平面交、二分
n≤1000000 =>O(n),以及常数较小的O(nlogn.)算法=> hash、双指针扫描、kmp、AC自动机,常数比较小的O(nlogn)的做法: sort、树状数组、heap、dijkstra、spfa
n ≤107 => o(n),双指针扫描、 kmp、AC自动机、线性筛素数n≤109=> o(√n),判断质数
n≤1018 => o(logn),最大公约数
直接复制粘贴
进入考场,我们最好将下列头文件和主函数写到电脑的记事本里,这样的话,每写一个程序时直接复制粘贴即可,把时间省下来用于后面难题的调试!
//#include <bits/stdc++.h> 同样是ctrl+c,为啥要搞万能头呢
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
typedef long long LL;
const int N=1e5+10;
using namespace std;
int main()
{
return 0;
}
必背的数值
~
:1,2,4,8,16,32,64,128,256,512,1024
:32768
:65536
快速排序sort
sort(a,a+12);
sort(a,a+12,greater<int>() );
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[12]={12,32,234,45,65,9,0,11,2,3,-3,-21};
sort(a,a+12); //默认从小到大
for(int i=0;i<12;i++){
cout<<a[i]<<" ";
}
cout<<endl;
sort(a,a+12,greater<int>() ); //从大到小
for(int i=0;i<12;i++){
cout<<a[i]<<" ";
}
return 0;
}
-21 -3 0 2 3 9 11 12 32 45 65 234
234 65 45 32 12 11 9 3 2 0 -3 -21
使快排稳定:
stable_sort();
C++基础操作:
c=max(a,b);
c=min(a,b);
//交换变量值
swap(a,b)
//绝对值
m=abs(m);
//引用 取别名就是小名
int a=10;
int &b=a;
//对b的操作也就是对a的操作,a,b代表同一个东西
//引用必须初始化,引用不能更改,只给一个变量用
//异或 ^
//下标从0开始
s.insert(pos,s2);//第pos个位置插入s2
s.erase(pos,num);//第pos个位置删除num个字符
s.substr(pos,num);//第pos个位置截取num个字符 ,父串不变
s1.find(s2,pos);//在s1中从pos个位置找s2
//s1.find(s2) 默认从0开始
c++字符串和整数相互转换
字符串转整形:
typedef long long ll;
ll tra(string x) { //字符串转整
ll num=0;
ll n=1;
for (int i = x.length()-1; i >=0 ; i--) {
num += (x[i] - '0') * n;
n *= 10;
}
return num;
}
C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int val;
char str[20];
strcpy(str, "98993489");
val = atoi(str);
printf("字符串值 = %s, 整型值 = %d\n", str, val);
strcpy(str, "runoob.com");
val = atoi(str);
printf("字符串值 = %s, 整型值 = %d\n", str, val);
return(0);
}
注意:只有字符储存在char类型字符数组里面时才可以用,string不可用!!!
整形转字符串:
itoa(i ,num ,10 );
i ---- 需要转换成字符串的数字
num ---- 转换后保存字符串的变量
10 ---- 转换数字的基数(即进制)。10就是说按10进制转换数字。还可以是2,8,16等等你喜欢的进制类型
返回值:指向num这个字符串的指针
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
int number = 12345;
char str[32];
itoa(number, string, 10);
printf("integer = %d string = %s\n", number, str);
return 0;
}
最大公约数与最小公倍数
最大公约数:
int gcd(int a,int b) //欧几里得算法
{
return b?gcd(b,a%b):a;
}
while(m%n) //辗转相除法
{
int r=m%n;
m=n;
n=r;
}
cout<<n<<endl;
int gcd(int a, int b) //递归
{
if(b==0)
{
return a;
}
else
{
return gcd(b,a%b);
}
}
最小公倍数:
a*b/最大公约数=最小公倍数
二分查找函数lower_bound( )和upper_bound( )用法
在从小到大的排序数组中,
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
#include<bits/stdc++.h>
using namespace std;
int main() {
int a[] = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4};
sort(a,a+12);
cout << (lower_bound(a, a + 12, 4) - a) << endl; //输出 9
cout << (upper_bound(a, a + 12, 4) - a) << endl; //输出 12
cout << (lower_bound(a, a + 12, 1) - a) << endl; //输出 0
cout << (upper_bound(a, a + 12, 1) - a) << endl; //输出 3
cout << (lower_bound(a, a + 12, 3) - a) << endl; //输出 6
cout << (upper_bound(a, a + 12, 3) - a) << endl; //输出 9
cout << (lower_bound(a, a + 12, 5) - a) << endl; //输出 12
cout << (upper_bound(a, a + 12, 5) - a) << endl; //输出 12
cout << (lower_bound(a, a + 12, 0) - a) << endl; //输出 0
cout << (upper_bound(a, a + 12, 0) - a) << endl; //输出 0
return 0;
}
注:下标从零开始
在从大到小的排序数组中,
lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
没有greater<type>()默认升序查找
#include<bits/stdc++.h>
using namespace std;
int main() {
int a[] = {4, 4, 4, 3, 3, 3, 2, 2, 2, 1, 1, 1};
sort(a,a+12,greater<int>());
cout << (lower_bound(a, a + 12, 4,greater<int>()) - a) << endl; // 输出 0
cout << (upper_bound(a, a + 12, 4,greater<int>()) - a) << endl; // 输出 3
cout << (lower_bound(a, a + 12, 1,greater<int>()) - a) << endl; // 输出 9
cout << (upper_bound(a, a + 12, 1,greater<int>()) - a) << endl; // 输出 12
cout << (lower_bound(a, a + 12, 3,greater<int>()) - a) << endl; // 输出 3
cout << (upper_bound(a, a + 12, 3,greater<int>()) - a) << endl; // 输出 6
return 0;
}
注:注意边界!
strstr()函数与strchr()函数
strstr()用于查找字符串,strchr()用于查找字符;
详情:strstr():深入理解<string.h>库和内存函数(字符题目神器)-CSDN博客
strchr(): bool数组的使用 之 A-B (20 分)-CSDN博客
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "abbbcdef";
char arr2[] = "bbc";
char* ret=strstr(arr1,arr2);
char* res=strchr(arr1,'c');
if(ret)
printf("%s\n",ret);
if(res)
printf("%s\n",res);
return 0;
}
一些好用的stl
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s="1234567890";
string cr="abc";
string tmp;
//s+=cr;
tmp=s.substr(1,3);//(坐标,个数) 从下标1开始取3个
cout<<tmp<<endl;
s.insert(4,cr);//从0开始第num个位置插入
cout<<s<<endl;
cout<<s.find(tmp)<<endl; //"234"的首坐标位置
return 0;
}
nth_element使用方法:
nth_element(start,k,end,cmp)
nth_element(首地址,要查询第k小的地址,末地址) ;nth_element 就是在数组中查找第k小的元素并将其发到数组的第k个位置(从第0小开始)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
int a[100]={12,34,54,23,10,56,6,0,143,3};
nth_element(a,a+2,a+10);
cout<<a[2];
return 0;
}
pair(对组)用法
1.定义(构造):
1 pair<int, double> p1; //使用默认构造函数 2 pair<int, double> p2(1, 2.4); //用给定值初始化 3 pair<int, double> p3(p2); //拷贝构造函数
(1)利用make_pair:
1 pair<int, double> p1; 2 p1 = make_pair(1, 1.2);
(2)变量间赋值:
pair<int, double> p1(1, 1.2); pair<int, double> p2 = p1;
写题时常用操作:
typedef pair<int ,int> PII;
#define x first
#define y second
PII logs[N];
for(int i=0;i<n;i++) scanf("%d%d",&logs[i].x,&logs[i].y);