曲鹿纹狼
〇、标签整合
一、预先设置
1. Alt + {T,C}
添加:-std=c++14 -O2 -Wl,--stack=1073741824 -Wall
2. Alt + {T,V,A,O} + Enter
设置:编译完成,自动关闭。
二、简洁编程
(一)赋值·举一反三
pair<int,int> p = {3,7};//直接用"{}"来给pair赋值,结构体也适用,注意一一对应
array<int,3> a = {1,2,3};//数组a,int类型,长度为N
int x = 0,y = 0;
tie(x,y) = p;//直接将x,y依次赋值为p中的元素(等价于x=3,y=7)
tie(ignore,y) = p;//忽略掉p.first,将y赋值为p.second(等价于y=p.second)
//以下是c++17内容,仅作为知识拓展
auto [x,y,v] = a;//定义x,y,v表示数组a
for(auto [y,v]:ft[x]){}//遍历STL容器
(二)经验·用之无限
auto it = s.begin();//自动识别变量类型
unordered_map<int,int> mp;//当用不到顺序的时候,这个东西要快很多
ft[x].push_back({y,v});//通过list的形式代替pair<int,int>
for(auto k:{1,2}){}//遍历数组,k依次赋值为1、2
prev(it,x);//迭代器的下一位,x不填默认为1
next(it,x);//迭代器的上一位,x不填默认为1
int number = atoi(str);//将字符串str转换为number
iota(fa+1, fa+n+1, 1);//从1开始将fa[1]~fa[n]依次赋值为1~n
min_element(a+1,a+n+1);//求a[1~n]中的最小值,返回最小值的指针
max_element(a+1,a+n+1);//求a[1~n]中的最大值,返回最大值的指针
cerr<<a;//输出a到控制板上,并不会影响实际输出
assert(A);//如果不满足事件A,程序会提前终止,并且返回当前所在行
exit(0);//无论在哪个函数,直接结束运行进程
三、代码模板
#include<bits/stdc++.h>
#include<vector>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
#define show(a,b) {For(i,1,b) cerr<<a[i]<<' ';cerr<<'\n';}
using namespace std;
#define P pair<int,int>
#define int long long
#define x first
#define y second
#define in(x,l,r) (l<=x && x<=r)
inline int rd(){
char c;bool f=false;while(!isdigit(c=getchar()))f=c=='-';int x=c^48;
while(isdigit(c=getchar())){x=(((x<<2)+x)<<1)+(c^48);}return f?-x:x;
}template<typename G>
void write(G x){
if(x<0) putchar('-'),write(-x);
else if(x<=9) putchar(x+'0');
else write(x/10), putchar(x%10+'0');
}constexpr int inf = 0x3f3f3f3f3f3f3f3f;
constexpr int N = 201234;
bool ST;
void Solve(){
}
bool ED;
signed main(){
cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
int T = 1;double Tim = clock();
while(T--) Solve();
return cerr<<"TIME:"<<(clock()-Tim)/CLOCKS_PER_SEC,0;
}
cin,cout版
#include<bits/stdc++.h>
#include<vector>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
#define show(a,b) {For(i,1,b) cerr<<a[i]<<' ';cerr<<'\n';}
using namespace std;
#define P pair<int,int>
#define int long long
#define x first
#define y second
#define in(x,l,r) (l<=x && x<=r)
inline int rd(){int x;return cin>>x,x;}
const int inf = 0x3f3f3f3f3f3f3f3f;
const int N = 201234;
bool ST;
void Solve(){
}
bool ED;
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
int T = 1;double Tim = clock();
while(T--) Solve();
return cerr<<"TIME:"<<(clock()-Tim)/CLOCKS_PER_SEC,0;
}
四、常用知识
(一)宏定义的使用
在应有的地方加入宏定义,然后及时取消,这是一个非常好的习惯。
#define mid ((l+r)>>1)
#undef mid
(二)取模优化
inline void add(int &x,int y){if((x+=y)>=mod)x-=mod;}//这个括号非常重要!!!
inline void sub(int &x,int y){if((x-=y)<0)x+=mod;}//这个括号非常重要!!!
inline void mul(int &x,int y){x=x*y%mod;}
(三)函数的初始化与重载运算符
struct Tr{
int x,y;Tr(int a){x = a,y = 0;}//初始化 x=a=1,y=0
bool operator<(const Tr b){return y<b.y;}//可以在STL容器中更新“<”符号的比较方式
}thi(1);
(四)内部函数的定义
$\qquad$ 若没有指定返回类型,则返回类型将被自动推断(行为与用 auto
声明返回值的普通函数一致)。具体的,如果函数体中没有 return
语句,返回类型将被推导为 void
,否则根据返回值推导。 (摘自 OI Wiki )
sort(a.begin(),a.end(),[](I x,I y){return x.id<y.id;});//从小到大排序
auto print = [](auto x)->int{return x;};//标明函数类型
//在函数内部,可以定义:
auto cal = [&](int l, int r, int v){c[l] += v, c[r+1] -= v;};//[&]表示引用所有全局变量地址
auto cal = [=](int l, int r, int v){c[l] += v, c[r+1] -= v;};//[=]表示引用所有全局变量的值
auto cal = [&x,&y](int l,int r){return x=l,y=r,x+y;};//引用外部变量地址,引入传入变量的值
auto cal = [x,y](int &l,int &r){return x=l,y=r,x+y;};//引用外部变量的值,引入传入变量地址
(五)数组的内存分配
该方法适用于给定 $n*m<=10^6$ 的情况。
const int N = 2012345;
int n,m;
struct node{
int v[N<<2];
int *operator[](int x){return v + x*m;}
}c;//引用的时候可以直接使用c[i][j]
signed main(){
cin>>n>>m;
For(i,1,n) For(j,1,m) cin>>c[i][j];
}
(六)数组的负值引用
const int N = 101234;
int A[N],*a,n;
signed main(){
cin>>n;
a = A+n;
For(i,-n,n) cin>>a[i];
}
(七)goto函数的应用
只需要定义一行函数名字,如下所示:
jump:;
程序执行时可以直接跳到当前行,并执行这一行之后的语句:(注意,$\verb!jump:!$ 标签要在 $\verb!goto!$ 之前定义)
goto jump;
(八)switch函数的应用
switch(a){
case 1:{程序A;break;}
case 2:{程序B;}
case 3:{程序C;break}
case 4: case 5:{程序D;break;}
}
样例解释
在下面的switch
函数中,$a$ 可以为 $1,2,3,4$ :
- 若 $a==1$,执行程序A;
- 若 $a==2$,执行程序B和程序C;
- 若 $a==3$,执行程序C;
- 若 $a==4$ 或 $a==5$ ,执行程序D;
可见,当case x
语句满足时,会直接贯穿执行后面所有的语句,直到遇到后面的第一个break
语句后停止。
(九)__builtin函数的应用
__builtin_ctzll(x);//返回x的二进制表示下末尾0的个数
__builtin_clzll(x);//返回x的二进制表示下前导0的个数
__builtin_popcountll(x);//返回x的二进制表示下1的个数
//注意:"ll"表示x的类型为longlong
(十)next_permutation的应用
还有一个 prev_permutation
的函数,这两个函数可以得出当前排列的下一个或上一个。
int a[N]={1,2,3,4...};
do{
//如果已经是最大的排列(n,n-1,n-2...3,2,1),返回false
}while(next_permutation(a+1,a+n+1))
(十一)shuffle函数的应用
这个函数可以将数组随机排列,只是需要传入随机数种子。
mt19937_64 rr(time(0));
shuffle(col+1,col+tot+1,rr);//将数组col随机排列
(十一)bitset容器的运用
$\qquad$bitset
在处理 $bool$ 型数组时有很多优势,它可以直接使用&,^,|,~
进行二进制下的运算,时间复杂度却比for
循环的 $O(n)$ 要快,约为 $O(\frac{n}{\omega})$ ,而神之又神的vst._Find_first
与vst._Find_next
函数也可以在 $O(\frac{n}{\omega})$ 的时间复杂度运行。一般情况下, $\omega$ 的值为 $64$ 。
$\qquad$可以参看这个博客: C++ bitset(位图)的介绍和使用-CSDN博客
bitset<N> vst,a,b;//定义长度为N的bool数组vst
vst.reset();//重置bitset为0
vst = ~vst;//将vst取反
vst = a|b, vst = a&b, vst = a^b;//进行符号运算
int x = vst._Find_first();//找到vst的第一个1的位置
int y = vst._Find_next(x);//找到vst中x位置后面第一个1的位置
(十二)list容器的运用
浅谈
$\qquad$每次手写链表的时候都很容易把自己搞晕,甚至对链表产生了恐惧感,现在用STL
容器封装后便舒服了许多。list
容器可以使用STL
容器的基本函数加入和删除,也可以使用insert
来对特定位置进行插入与删除。十分有趣的是,这个容器支持在前面和后面添加元素,那deque
不就失业了吗?
$\qquad$好吧,经过测验,list
至少比deque
慢了 $5$ 倍左右,常数巨大,建议不要乱用。
#include<list>
list<int> lis;
lis.push_back(x),lis.pop_back();
lis.push_front(x),lis.pop_front();
auto x = lis.begin();
lis.insert(x,y);//在指针x前面插入元素y
lis.erase(x);//删除指针x对应的元素。注意:删除后该指针无法使用
五、mathjax的使用
(一)字体
$a$ //公式格式,一般用来描述函数或方程
`a` //代码格式,一般用来表示容器(map)
$\verb!a!$ //代码格式,一般用来表示语句(int)
$\mathrm{a}$ //正体格式,一般用来表示方法(dp)
效果
$\ Hello World$
Hello World
$\verb!Hello World!$
$\mathrm{Hello\ World}$
(二)格式
<details><summary> b </summary>c</details> //缩略,b是标题,c是内容
<details open><summary> b </summary>c</details> //默认为展开的缩略
> //块引用,可用于强调或者引用文章
----------------//(一直横线到最右边)这是一条分割线
效果
Greatings
Hello World展开
我被展开啦~这个东西还是有点作用的叭~
其实就是上面的这一条线,一直按“-”到最右边顶格,然后 Enter 就可以了。
(三)常忘 mathjax 公式
$\binom{m}{n}$ //组合数的表示
$\frac{m}{n}$ //分数的表示
$\left(\right)$ //“大”括号的表示
$\le \ge$ //小于等于和大于等于
$\forall$ //任何
$\exists$ //存在
$\overline{x}$ //上横线
$\vert x\vert$ //绝对值,也可以做竖线
$\leftarrow$ //箭头,"方向"+"arrow"即可
$\Leftarrow$ //推导,"方向"+"arrow"即可
$\land \lor$ //逻辑与 和 逻辑或
$\infty$ //无穷
效果:
- $\binom{m}{n}$ //主要适用于表示 $C_{n}^{m}$
- $\frac{m}{n}$
- $\left(\sum_{\sum\frac{c}{d}}^{\sum \frac{a}{b}}\right)$ //我只是想表达这个括号真的可以很大
- $\le \ge$
- $\forall$
- $\exists$
- $\overline{x}$
- $\vert x\vert$
- $\leftarrow\downarrow\rightarrow\uparrow$
- $\Leftarrow\Downarrow\Rightarrow\Uparrow$
- $\land \lor$
- $\infty$
六、资料
$\qquad$PDF来源:http://ssoier.cn:8088/stl.html
$\qquad$C++_string类(C++字符串).pdf
$\qquad$lemon评测软件SPJ说明.pdf
$\qquad$常用的排序算法.pdf
$\qquad$关于STL容器的简单总结.pdf