知识点一:宏定义
1.将这些代码封装直接使用,大幅增加编写代码的速度,以节省出更多的时间
用于思考。
2.更容易DBUG
个人模板整理↓
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define ull unsigned long long
#define ll long long
#define pb push_back
#define mk make pair
#define _rep(i,a,b) for(int i=(a):i<=(b);i++)
#define sz(x) (x.size())
知识点二:快读快写
注意事项:
1.输入输出的数据过大时可以使用
2.字符串类型输入输出无法使用快读快写
3.输入输出方式要对应,cin 对应 cout,scanf 对应 printf,快读对应快写
4.不使用 cin 和 cout 时不要关同步,否则程序输出会出现问题
原理:将数字输入过程转化为一个字符一个字符输入的过程,输入完毕后转换为数字。
题目&代码模板:
A+B快速版
时间限制:2秒 内存限制:128M
题目描述
给定 n 对数 a,b ,求出所有的 a+b 。
输入描述
第一行输入 n
接下来 n 行每行有两个整数 ,a,b
输出描述
输出 n 行,n 对 a+b 的结果
输入样例
2
1 1
2 2
输出样例
2
4
数据范围
1<=n<=5×10^6,1<=a,b<=10^9
解题思路
题目本身很简单,但n的范围为5×10^6 ,普通的输入输出一定会超时,因此考虑快读快写
AC代码
#include<bits/stdc++.h>
using namespace std;
template<typename T>
void read(T& x){
x=0;
char ch=getchar();
long long f=1;
while(!isdigit(ch)){
if(ch=='-'){//处理负数
f*=-1;
}
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-48;//字符转数字
ch=getchar();
}
x*=f;
}
template<typename T,typename... Args>//不定参数,可输入多个参数
void read(T& first,Args&...args){
read(first);
read(args...);
}
template<typename T>
void write(T arg){
T x=arg;
if(x<0){
putchar('-');//承接上文
x=-x;
}
if(x>9){
write(x/10);//递归输出
}
putchar(x%10+'0');
}
template<typename T,typename... Ts>
void write(T arg,Ts... args){
write(arg);
if(sizeof...(args)!=0){
putchar(' ');
write(args...);
}
}
int n;
long long ans;
int main(){
read(n);
long long x,y;
for(int i=1;i<=n;i++){
read(x,y);
write(x+y);
putchar('\n');
}
}
知识点三:STL补充
1.优先队列
先上题目↓
合并果子
时间限制:1秒 内存限制:128M
题目描述
在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。 每一次合并,多多可以把两堆果子合并到一起,消耗的体力等于两堆果子的重量之和。可以看出,所有的果子经过n-1次合并之后,就只剩下一堆了。多多在合并果子时总共消耗的体力等于每次合并所耗体力之和。 因为还要花大力气把这些果子搬回家,所以多多在合并果子时要尽可能地节省体力。假定每个果子重量都为1,并且已知果子的种类数和每种果子的数目,你的任务是设计出合并的次序方案,使多多耗费的体力最少,并输出这个最小的体力耗费值。 例如有3种果子,数目依次为1,2,9。可以先将1、2堆合并,新堆数目为3,耗费体力为3。接着,将新堆与原先的第三堆合并,又得到新的堆,数目为12,耗费体力为12。所以多多总共耗费体力=3+12=15。可以证明15为最小的体力耗费值。
输入描述
输入包括两行,第一行是一个整数n(1< =n< =10000),表示果子的种类数。第二行包含n个整数,用空格分隔,第i个整数ai(1< =ai< =20000)是第i种果子的数目。
输出描述
输出包括一行,这一行只包含一个整数,也就是最小的体力耗费值。输入数据保证这个值小于2^31。
样例
输入
3
1 2 9
输出
15
提示
对于30%的数据,保证有n< =1000: 对于50%的数据,保证有n< =5000; 对于全部的数据,保证有n< =10000。
解题思路
由题目可以推出优先合并最小的两堆果子费力最小,因此可以考虑优先队列(注意要用小根堆),每次先选出最小的两堆果子合并,将合并耗费的体力即加入答案又压入队列,直到队列内只剩1个数此时输出答案。
AC代码
#include<bits/stdc++.h>
using namespace std;
long long n,a[40005],ans;
priority_queue<int,vector<int>,greater<int> >q;
int main(){
cin>>n;
long long c;
for(int i=1;i<=n;i++){
cin>>c;
q.push(c);
}
long long cnt=0;
while(q.size()>1){
cnt=0;
ans+=q.top();
cnt+=q.top();
q.pop();
ans+=q.top();
cnt+=q.top();
q.pop();
q.push(cnt);
}
cout<<ans;
}
2.map
先上题目↓
分类
时间限制:1秒 内存限制:128M
题目描述
仓库里面堆积着很多的货物。小可放假归来,发现仓库里多了许多的货物。
小可作为仓库管理员,需要对新多出来的货物进行分类整理。但是这段时间多出来的货物太多了,你能帮小可整理一下吗?
输入描述
第一行一个正整数T(1≤ T≤ 10),代表有T组数据。
对于每组数据,第一行有一个正整数n,代表有n条入库记录。
接下来有n行入库记录。
每个入库记录由字符串a,b和一个正整数m(1≤ m≤ 100)组成,a是货物名,b是货物来源,m是数量。这两个字符串的长度都不长于80。
输出描述
请输出合并整理后格式正确的货物统计表。格式为:
把货物按照来源地分类,来源地按照字典序排序输出。每个来源地都有下级分类。
每个来源地下级分类中,每一行输出三个空格,一个|,四个-,用来保持缩进。子分类中,将来源地是此来源地的货物按照字典序排序,每个货物后面有一个括号,里面写货物的总数量。
具体格式参考样例
样例
输入
1
5
pencil shandong 3
eraser guangdong 1
water sichuan 1
eraser guangdong 3
water guangdong 1
输出
guangdong
|----eraser(4)
|----water(1)
shandong
|----pencil(3)
sichuan
|----water(1)
解题思路
本题有三种信息要记录,按优先级从高到低排列为:货物名,货物来源,数量。
同时,从答案的层次来看,用map套map是个不错的选择。
有了这样的思路,保存、整理、输出都很简单了,详见注释
AC代码
#include<bits/stdc++.h>
using namespace std;
map<string,map<string,int> >ma;
int n,m,t;
string a,b,tmp;
int main(){
cin>>t;
while(t--){//多组输入↓
cin>>n;
map<string,map<string,int> >::iterator it;
for(int i=1;i<=n;i++){
cin>>a>>b;
cin>>m;
ma[b][a]+=m;
}
for(it=ma.begin();it!=ma.end();it++){//外层迭代器遍历产地
map<string,int>::iterator itt;
cout<<it->first<<'\n';
for(itt=(it->second).begin();itt!=(it->second).end();itt++){//内层迭代器遍历品名并输出数量
cout<<" |----"<<itt->first<<'('<<itt->second<<')'<<'\n';
}
}
ma.clear();//记得重置↑
cout<<'\n';
}
}