〇、常用头文件总结
前4项第一个字符:i c a i(我看见了一个我)
第5项全称:cstring(一个字符串飘过)
后4项最后一个字符:b h e s(不好意思)
至于其他STL,要用什么就加什么。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cctype>
#include<climits>
一、输入输出优化
(一)输入优化
int in(){
int f=1,x=0;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return f*x;
}
(二)输出优化
void out(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>=10)out(x/10);
putchar(x%10+'0');
}
二、基本算法
(一)二分答案
int work(){
int L=1,R=n;
while(L<R){
int M=L+R>>1;
if(check())R=M;
else L=M+1;
}
return L;
}
(二)排序
1.离散化
void lsh(){
for(int i=1;i<=n;i++)tmp[i]=a[i];
sort(tmp+1,tmp+1+n);
int m=unique(tmp+1,tmp+1+n)-tmp-1;
for(int i=1;i<=n;i++)a[i]=lower_bound(tmp+1,tmp+1+n,a[i])-tmp;
//此时a数组保存的是原来的数被离散化后的数
}
2.归并排序
void merge(int l,int r){
if(l==r)return;
int m=l+r>>1,i=l,j=m+1,k=l;
merge(l,m);
merge(m+1,r);
while(i<=m&&j<=r){
if(a[i]<=a[j])b[k++]=a[i++];
else b[k++]=a[j++];//cnt+=m-i+1
}
while(i<=m)b[k++]=a[i++];
while(j<=r)b[k++]=a[j++];
for(k=l;k<=r;k++)a[k]=b[k];
}
(三)倍增
1.ST算法
(1)预处理
void init(){
int t=log2(n)+1;
for(int i=1;i<=n;i++)maxx[i][0]=a[i];
for(int j=1;j<t;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
maxx[i][j]=max(maxx[i][j-1],maxx[i+(1<<(j-1))][j-1]);
}
}
}
(2)查询
int ask(int l,int r){
int k=log2(r-l+1);
return max(maxx[l][k],maxx[r-(1<<k)+1][k]);
}
三、基本数据结构
(一)Hash
1.Hash表
int check(int x){
int tmp=x%mod;
for(int i=0;i<hash[tmp].size();i++){
if(hash[tmp][i]==x)return 1;
}
hash[tmp].push_back(x);
return 0;
}
2.字符串Hash
int p,mod;
int hash(char *s){
int len=strlen(s+1),ans=0;
for(int i=1;i<=len;i++)ans=(ans*p+s[i])%mod;
return ans;
}
(二)Trie
1.插入
void insert(char *s){
int len=strlen(s),p=1;
for(int i=0;i<len;i++){
int ch=s[i]-'a';
if(!trie[p][ch])trie[p][ch]=++cnt;
p=trie[p][ch];
}
end[p]=1;
}
2.查询
int search(char *s){
int len=strlen(s),p=1;
for(int i=0;i<len;i++){
int ch=s[i]-'a';
p=trie[p][ch];
if(!p)return 0;
}
return end[p];
}
四、数论
(一)筛法
1.埃氏筛法
(1)初始化
void init(){
for(int i=2;i<=n;i++){
if(vis[i])continue;
for(int j=i;j<=n/i;j++)vis[i*j]=1;
}
}
(2)查询
int isprime(int x){
return !vis[x];
}
(二)费马小定理
1.求逆元
(1)快速幂
int Pow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
(2)查询
int ny(int x){
return Pow(x,mod-2);
}
(三)扩展欧几里得
int x,y;
void exgcd(int a,int b){
if(!b){
x=1,y=0;
return;
}
exgcd(b,a%b);
int t=x;
x=y,y=t-a/b*y;
}
//此时x和y是方程的一组特解
//ax+by=c的通解是x=c/gcd*x0+k*b/d,y=c/gcd*y0+k*a/d(k∈Z)此处x0和y0是exgcd得到的特解
(四)矩阵乘法
(五)卡特兰数
1.初始化
void init(){
f[0][0]=1;
for(int i=1;i<=n;i++){
f[i][0]=1;
for(int j=1;j<=i;j++)f[i][j]=f[i-1][j-1]+f[i-1][j];
}
}
2.查询
int ask(int x){
return f[2*x][x]/(x+1);
}
(六)高精度
1.加法
string Add(string A,string B){
int la=A.size(),lb=B.size(),lc=1,a[100005],b[100005],c[100005],x=0;
for(int i=0;i<la;i++)a[la-i]=A[i]-'0';
for(int i=0;i<lb;i++)b[lb-i]=B[i]-'0';
while(lc<=la||lc<=lb){
c[lc]=a[lc]+b[lc]+x;
x=c[lc]/10;
c[lc]%=10;
lc++;
}
c[lc]=x;
while(!c[lc]&&lc>1)lc--;
string ans;
for(int i=lc;i>=1;i--)ans+=c[i]+'0';
return ans;
}
2.减法
string Minus(string A,string B){
int la=A.size(),lb=B.size(),lc=1,a[100005],b[100005],c[100005];
if(la<lb||la==lb&&A<B){
string tmp;
tmp=A;
A=B;
B=tmp;
}
la=A.size(),lb=B.size();
for(int i=0;i<la;i++)a[la-i]=A[i]-'0';
for(int i=0;i<lb;i++)b[lb-i]=B[i]-'0';
while(lc<=la){
if(a[lc]<b[lc])a[lc]+=10,a[lc+1]--;
c[lc]=a[lc]-b[lc];
lc++;
}
while(!c[lc]&&lc>1)lc--;
string ans;
for(int i=lc;i>=1;i--)ans+=c[i]+'0';
return ans;
}
3.乘法
string Mul(string A,string B){
int la=A.size(),lb=B.size(),lc=la+lb,a[10005],b[10005],c[10005],x=0;
for(int i=0;i<la;i++)a[la-i]=A[i]-'0';
for(int i=0;i<lb;i++)b[lb-i]=B[i]-'0';
for(int i=1;i<=la;i++){
x=0;
for(int j=1;j<=lb;j++){
c[i+j-1]+=a[i]*b[j]+x;
x=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[i+lb]=x;
}
while(!c[lc]&&lc>1)lc--;
string ans;
for(int i=lc;i>=1;i--)ans+=c[i]+'0';
return ans;
}
4.除法
string Div(string A,int b){
int la=A.size(),lc=1,a[10005],c[10005],x=0;
for(int i=0;i<la;i++)a[i+1]=A[i]-'0';
while(lc<=la){
c[lc]=(x*10+a[lc])/b;
x=(x*10+a[lc])%b;
lc++;
}
lc=1;
while(!c[lc]&&lc<la)lc++;
string ans;
for(int i=lc;i<=la;i++)ans+=c[i]+'0';
return ans;
}
五、数据结构进阶
(一)并查集
1.初始化
void init(){
for(int i=1;i<=n;i++)fa[i]=i;
}
2.查询
int get(int x){
if(x==fa[x])return x;
return fa[x]=get(fa[x]);
}
3.合并
void merge(int x,int y){
fa[get(x)]=get(y);
}
(二)树状数组
(三)线段树
(四)分块
六、动态规划
(一)求子树节点数
1.预处理
void dfs(int u,int fa){
size[u]++;
for(int i=head[u];i;i=Next[i]){
int v=to[i];
if(fa==v)continue;
dfs(v,u);
size[u]+=size[v];
}
}
2.查询
int ask(int x){
return size[x];
}
七、图论
(一)最短路
1.Floyd
void floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(k!=i&&k!=j&&i!=j){
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
}
}
}
}
2.Dijkstra
void dijkstra(int x){
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
dis[x]=0;
priority_queue<pair<int,int> > q;
q.push(make_pair(0,x));
while(q.size()){
int u=q.top().second;
q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=head[u];i;i=Next[i]){
int v=to[i],w=wei[i];
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push(make_pair(-dis[v],v));
}
}
}
}
3.SPFA
void spfa(int x){
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
vis[x]=1;
dis[x]=0;
queue<int> q;
q.push(x);
while(q.size()){
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i;i=Next[i]){
int v=to[i],w=wei[i];
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]){
vis[v]=1;
q.push(v);
}
}
}
}
}
(二)最小生成树
1.Kruskal
int get(int x){
if(x==fa[x])return x;
return fa[x]=get(fa[x]);
}
int kruskal(){
int ans=0;
sort(a+1,a+1+m);
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
int x=get(a[i].u),y=get(a[i].v);
if(x==y)continue;
fa[x]=y;
ans+=a[i].w;
}
return ans;
}
(三)最近公共祖先
1.初始化
void bfs(int x){
dep[x]=0;
queue<int> q;
q.push(x);
while(q.size()){
int u=q.front();
q.pop();
for(int i=head[u];i;i=next[i]){
int v=to[i];
if(dep[v])continue;
dep[v]=dep[u]+1;
f[v][0]=u;
for(int j=1;j<=t;j++)f[v][j]=f[f[v][j-1]][j-1];
q.push(v);
}
}
}
2.查询
int lca(int u,int v){
if(dep[u]>dep[v])swap(u,v);
for(int i=t;i>=1;i--){
if(dep[f[v][i]]>=dep[u])v=f[v][i];
}
if(x==y)return x;
for(int i=t;i>=1;i--){
if(f[u][i]!=f[f][i]){
u=f[u][i];
v=f[v][i];
}
}
return f[u][0];
}