曲鹿纹狼


曲鹿纹狼

〇、标签整合

一、预先设置

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_firstvst._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)

效果

  1. $\ Hello World$

  2. Hello World

  3. $\verb!Hello World!$

  4. $\mathrm{Hello\ World}$

(二)格式

<details><summary> b </summary>c</details>			//缩略,b是标题,c是内容
<details open><summary> b </summary>c</details>		//默认为展开的缩略
> 				//块引用,可用于强调或者引用文章
----------------//(一直横线到最右边)这是一条分割线

效果

  1. GreatingsHello World
  2. 展开我被展开啦~
  3. 这个东西还是有点作用的叭~


  4. 其实就是上面的这一条线,一直按“-”到最右边顶格,然后 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$		//无穷

效果

  1. $\binom{m}{n}$ //主要适用于表示 $C_{n}^{m}$
  2. $\frac{m}{n}$
  3. $\left(\sum_{\sum\frac{c}{d}}^{\sum \frac{a}{b}}\right)$ //我只是想表达这个括号真的可以很大
  4. $\le \ge$
  5. $\forall$
  6. $\exists$
  7. $\overline{x}$
  8. $\vert x\vert$
  9. $\leftarrow\downarrow\rightarrow\uparrow$
  10. $\Leftarrow\Downarrow\Rightarrow\Uparrow$
  11. $\land \lor$
  12. $\infty$

六、资料

$\qquad$PDF来源:http://ssoier.cn:8088/stl.html

$\qquad$C++_string类(C++字符串).pdf

$\qquad$lemon评测软件SPJ说明.pdf

$\qquad$常用的排序算法.pdf

$\qquad$关于STL容器的简单总结.pdf


文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录