比赛小技巧

目录

由算法范围反推算法时间复杂度

直接复制粘贴 

必背的数值

快速排序sort

C++基础操作:

c++字符串和整数相互转换

 最大公约数与最小公倍数

二分查找函数lower_bound( )和upper_bound( )用法

在从小到大的排序数组中,

在从大到小的排序数组中,

strstr()函数与strchr()函数

一些好用的stl

 pair(对组)用法


由算法范围反推算法时间复杂度

一般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;
}

必背的数值

 2^{0} ~ 2^{10}:1,2,4,8,16,32,64,128,256,512,1024

2^{15}:32768

2^{16}:65536

2^{20} \approx 10^{6}

2^{63} \approx 10^{18}

快速排序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;
}

练习: P1923 【深基9.例4】求第 k 小的数 

 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);

1238. 日志统计 - AcWing题库

  • 20
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NO.-LL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值