前言
c++的奥秘无穷,和数学一样,永远值得我们去研究.
我也只能略举一二,如果这对你没有什么用处,请点击右上角的那个
×.
×
.
具体内容
我先打个备注:
如果你发现你的c++使用了这些函数以后CE报错,那可能是你没有开c++11.有一些函数是在c++11里面出现的.
cctype
这个头文件看似大部分是判断字符类型的内容,但是据说比直接写要快..
你要说这个算奇技淫巧我觉得也不算,但是这些真的很好用.
比较常用的几个是这些:
isalpha(c)
判断字符
c
c
是否是字母.
isupper(c)
判断字符是否是大写字母.
islower(c)
判断字符
c
c
是否是小写字母.
isdigit(c)
判断字符是否是数字字符.
isspace(c)
判断字符
c
c
是否是空格,换行符或者tab.
这样只需要7个字母,你就可以判断一个字符是什么类型的了.
比较上原来的c>='0'&&c<='9'
,确实好打了很多.
我会说这是做CF的时候抢速度用的么 ?
deque
这是双端队列.它所在的头文件是<queue>
.
顾名思义,它的两端都可以加入和弹出元素.
所以自然有以下的几个操作.
q.push_back(x)
在双端队列的队尾加入一个元素
x
x
.
q.push_front(x)
在双端队列的队头加入一个元素
x
x
q.pop_back()
弹出队尾的元素.
q.pop_front()
弹出队头的元素.
q.front()
队头的元素.
q.back()
队尾的元素.
那你就说了,这些东西普通的queue
也可以做到,我为什么要用双端队列呢?
我会告诉你我是为了装B写单调队列吗?
你想到了吧.
我们来看看用双端队列完成的单调队列是怎么样的.
luogu p1440 求m区间内的最小值
相信大家都会写单调队列,我就不解释代码了,大家自己体会一下.
#include<bits/stdc++.h> //Ithea Myse Valgulious
} using namespace chtholly; //省略快读快写
using namespace std;
const int yuzu=2e6;
int a[yuzu|10];
deque<int> q;
int main()
{
int i,n=read(),m=read();
for (i=1; i<=n; ++i)
{
a[i]=read();
printf("%d\n",a[q.front()]);
for (; !q.empty()&&i-m>=q.front(); q.pop_front());
for (; !q.empty()&&a[i]<=a[q.back()]; q.pop_back());
q.push_back(i);
}
}//非常漂亮的过去了.是不是很美?
string
#include<string>
虽然字符串的类型非常骚,但是常用的没这么多,所以知道那些就可以了.
不过还是有两个神技被大部分人忽略了.
第一个叫std::to_string
.
这个函数能够把数字(可以是整形数,也可以是浮点数)直接转换成字符串.
真的非常好用,我们看看例题.
给出一个长度为偶数的正整数n,判断它前一半位数的数字之和是否等于后一半. n<=1e9.
#include<bits/stdc++.h>
using namespace std;
int main()
{
int ans=0;
int n;
cin>>n;
string a=to_string(n);
for (int i=0; i<a.size(); ++i)
{
if (i<a.size()/2) ans+=a[i];
else ans-=a[i];
}
puts(ans==0?"Yes":"No");
}
我手打了上面的代码,大约在一分钟左右.非常快.
第二个是std::stoi
.
和atoi
一样的是,这个函数能把string
变成数字.
同理也是能变成整数或者浮点数.
要注意的是,转换的时候字符串中不能有非法字符,也不能超过数据范围,否则会当场报错.
还有这两个函数都在c++11里面.
好,我们准备下一个.
algorithm
这个头文件里骚的东西真的多.
next_permutation,prev_permutation
.
这两个东西有多厉害不用我说吧,枚举全排列就靠它了.
min_element,max_element
,
返回范围中最小/最大元素的迭代器.
fill(iterator first,iterator last,val)
你是不是怕memset
出一些奇怪的问题?用fill
!.
nth_element(it first,it nth,it last)
,
能让第大的元素处在区间的第
n
n
个.
unique(it first,it last)
;
将区间去重(注意只能对连续相同的元素去重)并返回元素的个数的位置指向的迭代器.
所以如果要达到真实去重的效果请对区间排序.
举例:
vector<int> v={2,3,5,5,4,2,2,5};
sort(v.begin(),v.end());//v={2,2,2,3,4,5,5,5};
vector<int>::iterator it=unique(v.begin(),v.end());//v={2,3,4,5,?,?,?,?};
cout<<it-v.begin()<<endl;
for (auto i:v) cout<<i<<" ";
输出:
4
2 3 4 5 //4 5 5 5(后面是什么不重要了.)
最后是神奇的random_shuffle
,也就是随机化区间内的所有元素了.
给你的好友来上一句
#define sort random_shuffle
他会非常高兴的.(哈哈哈哈)
ctime
时间!关于日期和时间的计算在信息学竞赛中非常重要.
这一次我来介绍一下ctime
中两个神奇的函数.
1:clock
这个东西可以算代码运行的时间.用法是这样的:
clock_t nowtime=clock();
...
cout<<clock()-nowtime<<endl;
这时候输出了一个数字,单位是毫秒,表示运行的时间.
这样就可以判断你是不是了.
爆搜到时限之后直接输出
−1
−
1
其实也是用的这种方法.
2.difftime
这个函数用来算两个时间之间的时间差.
用法?
首先在c++中,时间是由一个叫
tm
t
m
的结构体储存的.
这个结构体有9个成员.
struct tm{
int tm_sec;//秒
int tm_min;//分钟
int tm_hour;//小时
int tm_mday;//(这个月的)哪一天
int tm_mon;//月
int tm_year;//年(这个年是以1900作为起始时间的,设置的时候要减去1900)
int tm_wday;//星期几,0表示星期天
int tm_yday;//今年从1月1日开始的第几天
int tm_isdst;//是否是夏令时
};
然后有一个函数mktime(&t)
可以将结构体表示的时间变为秒表示的时间.
接下来用difftime
函数可以算出两个日期之间差的秒数,除以
86400
86400
就是天数.
举例计算从今年7月22日(谁的生日?) 到今天 (7月27日) 的天数.应该是5天.
int main()
{
tm t1= {0},t2= {0};
t1.tm_year=2018-1900,t1.tm_mon=6,t1.tm_mday=22;
t2.tm_year=2018-1900,t2.tm_mon=6,t2.tm_mday=27;
cout<<difftime(mktime(&t2),mktime(&t1))/86400<<endl;
}//输出5
要注意的点:
1.年份从1900开始,月份以1月为准,要减掉1;
2.计算的时间的范围在[1900,3000]之间.别过界了.
这样我们再也不怕询问时间的问题了!
stringstream
stringstream的头文件是<sstream>
.
终于到压轴的神器出场了.这是我不得不对c++顶礼膜拜的原因之一.
它的适用范围很广(面对毒瘤出题人)
而我仅仅是挖开了冰山一角.
我们来看例题.
洛谷p1020 导弹拦截
这题题目不难,我们就看它的输入.
想必大家都是while (scanf("%d",&n)!=EOF){}
之类的读法.
现在我们把题目改一下.
本题包含多组数据,每行一组,包含若干个数字.
这下完了.
你不给我数据组数就算了,每组数据也不给我多少个数字,我怎么读啊!
sb出题人,*************
(已被屏蔽)
这题从读入上就已经干倒了一群人.
那么该怎么办呢?
考虑用getchar()
,碰到空格换一个数字,碰到回车换一组数据.
非常麻烦.
那用getline
,每次读入一组数据,用奇怪的方法搞来搞去.
还是很麻烦.
这时候stringstream
出场了.
const int yuzu=1e5;
int a[yuzu|10],n;
int main()
{
string s;
for (; getline(cin,s);)
{
stringstream llx(s);
n=0;
for (; llx>>a[++n];);
}
}
字符串流也是流的一种,可以用来输入.上题就是一种可能的方法.
那么还有一个问题也可以迎刃而解.
给出一串用奇怪符号(里面包括空格)隔开的数字,输出它们的和.
样例:
input:
{15/;; ;8787*- )),|^&&1<<>>}
output:
8803
在get字符串以后把里面不是数字的符号都变成空格,然后用stringstream
输入就可以了.
配合c++11中的遍历方法和cctype
头文件使得代码非常简洁.
for (char &c:s) if (!isdigit(c)) c=' ';
我不会说我们需要这个东西是因为我作死在vjudge里提交topcoder没法测样例才学的.
sstream的缺点是慢了一点,但它真的很强!
总结
c++中还有很多神奇的东西,百玩不厌.
大家看了这篇博客后也可以自己去研究研究,希望大家能够找到更好玩的东西.
那么这篇博客就到这里了,谢谢大家.