模板
现在距离 2019 C S P 2019CSP 2019CSP 不到 24 24 24 小时了,积攒了很多的模板,为了不发最后一片学术博客进行记录,还可以算是给萌新 O I OI OI 一个总结吧,(这是最后这几天敲的,可能不会很全,希望评论多给扩充,应该仅限于今天吧,明天就上刑场了)大佬们,都发说说纪念了,我就发个博客吧(嘻嘻)
搜索:
dfs:
void dfs()//深搜
{
if() return ;//剪枝
over()//枚举出所有情况
{
dfs();//再次dfs
}
}
bfs:
void bfs//广搜
{
Q.push();
while(!Q.empty())
{
int x=Q.frond();
for()//枚举出所有情况
{
Q.push();
}
Q.pop();
}
}
图论:
floyed:
void floyed()
{
over(i,1,n) over(j,1,n) f[i][j]=ocean;
over(i,1,n) f[i][i]=0;
over(k,1,n) over(i,1,n) over(j,1,n)
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
}
spfa(bfs版):
void spfa(int s)
{
memset(d,0x3f,sizeof d);
memset(v,0,sizeof v);
queue<int>Q; Q.push(s); v[s]=1;d[s]=0;
while(!Q.empty())
{
int x=Q.front();Q.pop();v[x]=0;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver,z=e[i].edge;
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
if(!v[y]) v[y]=1,Q.push(y);
}
}
}
}
spfa(dfs版):
void spfa(int x)
{
v[x]=1;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver,z=e[i].edge;
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
if(v[y]) return ;
if(!spfa(y)) return ;
}
}
v[x]=0;
}
dijkstra:
priority_queue<pii,vector<pii>,greater<pii> > Q;
void dijkstra(int s)
{
over(i,1,n) d[i]=ocean;
memset(v,0,sizeof v);
Q.push(mp(0,s)); d[s]=0;
while(!Q.empty())
{
int x=Q.top().sec;Q.pop();
if(v[x]) continue; v[x]=1;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver,z=e[i].edge;
if(d[y]>d[x]+z)
d[y]=d[x]+z,Q.push(mp(d[y],y));
}
}
}
tarjan:
void tarjan(int x)
{
dfn[x]=low[x]=++deep; sta[++st]=x;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(!id[y]) low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x])
{
id[x]=++cnt;
while(x^sta[st]) id[sta[st--]]=cnt;
st--;
}
}
并查集:
int get(int x)
{
return x==fa[x]?x:fa[x]=get(fa[x]);
}
void incor(int x,int y)
{
int xx=get(x),yy=get(y);
if(xx!=yy) fa[xx]=yy;
}
kruskal:
void kruskal()
{
sort(e+1,e+tot+1,cmp);
over(i,1,tot)
{
int x=get(e[i].x),y=get(e[i].y);
if(x==y) continue;
ans+=e[i].edge;fa[x]=y;
if(++cnt==n-1) break;
}
}
二分图—匈牙利算法:
bool hgry(int x)
{
over(i,1,n) if(!v[i]&&g[x][i])
{
v[i]=1;
if(!pre[i]||hgry(pre[i]))
{pre[i]=x;return 1;}
}
}
over(i,1,n)
{
memset(v,0,sizeof v);
if(hgry(i)) ans++;
}
LCA:
void dfs(int x,int f)
{
fa[0][x]=f; deep[x]=deep[f]+1;
for(int i=last[x];i;i=e[i].next)
if(e[i].ver!=fa[0][x]) dfs(e[i].ver,x);
}
int lca(int x,int y)
{
if(deep[x]>deep[y]) swap(x,y);
for(int d=deep[y]-deep[x],i=0;d;d>>=1,i++) if(d&1) y=fa[i][y];
if(x==y) return x;
for(int i=21;i>=0;--i) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
return fa[0][x];
}
欧拉路:
void dfs(int x)
{
while(v[x].size())
{
int y=v[x].size()-1;
int k=v[x][y];v[x].resize(y);dfs(k);
}
ans[++cnt]=x;
}
//注意反向建边,回溯输出
//欧拉路:把所有边都走一遍不回到起点的
//有向图:所有入度=出度 或 起点出度-入度=1,终点入度-出度=1
//无向图:所有点偶数度 或 除了两个点为奇数度,其余为偶数度
//输出路径可以用vector.resize()或栈
拓扑排序:
void topu()
{
queue<int>Q;
over(i,1,n) if(!ru[i]) Q.push(i);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
ans[++cnt]=x;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver; ru[y]--;
if(!ru[y])Q.push(y);
}
}
if(cnt!=n) puts("-1");
else over(i,1,n) printf("%d ",ans[i]);
}
最短路记录路径:
void dijkstra(int s)
{
over(i,1,n) d[i]=ocean;
memset(v,0,sizeof v);
Q.push(mp(0,s)); d[s]=0;
while(!Q.empty())
{
int x=Q.top().sec;Q.pop();
if(v[x]) continue; v[x]=1;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver,z=e[i].edge;
if(d[y]>d[x]+z)
d[y]=d[x]+z,pre[y]=x,Q.push(mp(d[y],y));
}
}
}
void print(int s,int t)
{
if(d[t]==ocean) {printf("-1");return ;}
for(int i=n;i!=s;i=pre[i]) ans[++cnt]=i; ans[++cnt]=1;
lver(i,cnt,1) printf("%d ",ans[i]);
}
最短路路径计数:
void dijkstra(int s)
{
over(i,1,n) d[i]=ocean;
memset(v,0,sizeof v);
Q.push(mp(0,s)); d[s]=0;
while(!Q.empty())
{
int x=Q.top().sec;Q.pop();
if(v[x]) continue; v[x]=1;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver,z=e[i].edge;
if(d[y]==d[x]+z) cnt[y]=cnt[x]+cnt[y];
if(d[y]>d[x]+z) d[y]=d[x]+z,cnt[y]=cnt[x],Q.push(mp(d[y],y));
}
}
}
void spfa(int s)
{
memset(d,0x3f,sizeof d);
memset(v,0,sizeof v);
queue<int>Q; Q.push(s); v[s]=1; d[s]=0;
while(!Q.empty())
{
int x=Q.front(); Q.pop();v[x]=0;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver,z=e[i].edge;
if(d[y]>d[x]+z){d[y]=d[x]+z; if(!v[y]) v[y]=1,Q.push(y);}
if(d[y]==d[x]+z) ans[y]=(ans[y]+=ans[x])%mod;
}
}
}
割边:
void gb(int x,int fa)
{
dfn[x]=low[x]=++deep;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y])
{
gd(y,x); low[x]=min(low[x],low[y]);
if(dfn[x]<low[y])
col[x]=col[x^1]=1;
}
else if(y!=fa) low[x]=min(low[x],dfn[y]);
}
}
割点:
void gd(int x,int fa)
{
dfn[x]=low[x]=++deep; int flag=0;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].ver;
if(!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[x]);
if(low[y]>=dfn[x])
{
flag++;
if(x!=root||flag>1) col[x]=1;
}
}
else low[x]=min(low[x],dfn[y]);
}
}
数论:
快速幂:
int ksm(int a,int b)
{
int s=1;
while(b)
{
if(b&1) s=s*a%mod;
a=a*a%mod; b>>=1;
}
return s;
}
线性求阶乘及阶乘逆元:
void xxqny()
{
jc[0]=1; inv[0]=inv[1]=1;
over(i,1,sea) jc[i]=jc[i-1]*i%mod;
over(i,2,sea) inv[i]=mod-mod/i*inv[mod%i]%mod;
over(i,2,sea) inv[i]=inv[i-1]*inv[i]%mod;
}
gcd:
int gcd(int x,int y)
{
return !b?a:gcd(b,b%a);
}
lcm:
int lcm(int x,int y)
{
return x*y/gcd(x,y);
}
exgcd:
//是用来解线性同余方程 ax+by=c -> x=y(mod p) (同余符号)
//可以解出来其中一组解
void exgcd(int x,int y)
{
int s,int t;
if(!b){x=0,y=1;return ;}
s=exgcd(b,a%b,x,y);
t=y;x=y;y=t-a/b*y;
return s;
}
//求最小的正整数的解
int t=gcd(a,b);
if(c%t) printf("NO solution\n");
a/=t,b/=t,c/=t;
exgcd(a,b,x,y);
x=((c*x)%b+b)%b;
printf("%lld\n",x);
矩阵快速幂:
struct mrix{int mr[sea][sea];}a,b;
int n,k;
mrix mul(mrix a,mrix b)
{
mrix s; memset(s.mr,0,sizeof s.mr);
over(i,1,n) over(j,1,n) over(k,1,n)
{
s.mr[i][j]+=(a.mr[i][k]%mod)*(b.mr[i][k]%mod);
s.mr[i][j]%=mod;
}
return s;
}
void ksm(int x)
{
while(x)
{
if(x&1) a=mul(a,b);
b=mul(b,b); x>>=1;
}
}
线性筛:
void xxs()
{
memset(v,sizeof v);
int cnt=0; v[1]=1; v[0]=1;
over(i,2,n)
{
if(!v[i]) prim[cnt++]=i;
for(int j=0;i<cnt&&i*prim[j]<=n;j++)
{
v[prim[j]*i]=1;
if(i%prim[j]==0) break;
}
}
}
欧拉函数:
//欧拉函数:求一个数之前的互质对的个数
void euler(int x)
{
int s=x;
for(int i=1;i*i<=x;i++) if(x%i==0)
{
s=s/i*(i-1);
while(x%i==0) x/=i;
}
if(x!=1) s=s/x*(x-1);//可能会存在一个大于根号n的素因子
return s;
}
void eulerycl()
{
euler[1]=1;
over(i,2,n) euler[i]=i;
over(i,2,n) if(euler[i]==i) for(int j=i;j<=n;j+=i)
euler[j]=euler[j]/i*(i-1);
}
组合数:
int C(int x,int y)
{
return jc[x]*inv[y]%mod*inv[x-y]%mod;
}
动态规划:
01背包:
over(i,1,n) lver(j,V,v[i])
if(j>=v[i]) f[j]=max(f[j],f[j-v[i]]+w[i]);
printf("%d\n",f[V]);
完全背包:
over(i,1,n) over(j,v[i],V)
f[j]=max(f[j],f[j-v[i]]+w[i]);
printf("%d\n",f[V]);
数据结构:
初级数据结构:
栈:
//基础操作:
stack<int>st;
st.empty();
st.pop();
st.push();
st.top();
//单调栈:
over(i,1,n)
{
while(top&&a[st[top]]<a[i]) top--;
l[i]=st[top]; st[++top]=i;
}
队列:
//基础操作:
queue<int>Q;
Q.empty();
Q.pop();
Q.front();
Q.size();
Q.back();
//单调队列:
int head=1,tail=0;
over(i,1,n)
{
while(tail>=head&&i-q[head]+1>m) head++;
while(tail>=head&&a[i]>a[q[tail]]) tail--;
q[++tail]=i;
if(i>=m) cout<<a[q[h]]<<' ';
}
堆:
基础操作:
priority_queue<int,vector<int>,greater<int> >Q;//小根堆
priority_queue<int,int> >Q;//大根堆
Q.empty();
Q.pop();
Q.push();
Q.size();
Q.top();
set:
//基础操作:
set<int>se;
unordered_set<int>use;//(不排序) C++11
multiset_set<int>mse;//(不判重)
se.begin();//返回的是迭代器
se.clear();
se.empty();
se.end();//返回的是迭代器
se.erase();//erase(iterator) || st.erase(key_value) || it=st.find(30); st.erase(it,st.end());
se.find();//返回的是迭代器
se.insert();//insert(key_value); || inset(first,second);
se.upper_bound();//返回最后一个大于等于key_value的迭代器
se.lower_bound();//返回第一个大于等于key_value的迭代器
se.swap();//交换两个集合
se.size();//返回的是数值
se.max_size();//返回的是数值
se.count();//出现次数(可以判有无,可以是map)
map:
//基础操作
map<int,int>mvp;
map<char,int>mvp;
map<string,int>mvp;
mvp.clear();
list:
//基础操作
list<int>lis;
lis.clear();
lis.empty();
lis.size();
lis.front();
lis.back();
lis.begin();
lis.end();
lis.insert();
lis.push_back();
lis.push_front();
lis.pop_back();
lis.pop_front();
lis.merge();//合并两个链表并使之默认升序(也可改),
lis.sort();
lis.unique();
lis.swap();
lis.reverse();//逆置
lis.assign();
lis.remove();//lis.remove(x);删去数值为x的数
vector:
//基础操作
vector<int>V;
V.clear();
V.empty();
V.size();
V.begin();
V.end();
V.push_back();
V.pop_back();
V.max_size();
V.insert();
V.swap();
deque:
deque<int>dQ;
dQ.front();
dQ.back();
dQ.begin();
dQ.end();
dQ.clear();
dQ.empty();
dQ.pop_front();
dQ.pop_back();
dQ.swap();
dQ.push_front();
dQ.push_back();
dQ.insert();
dQ.max_size();
高级数据结构:
ST表:
//O(nlogn)预处理+O(1)查询
//仅能支持RMQ
void STycl()
{
int k=log(n)/log(2)+1; over(i,1,n) ST[i][0]=a[i];
over(j,1,t-1) over(i,1,n-(1<<j)+1)
ST[i][j]=max(S[i][j],ST[i+1<<(j-1)][j-1];
}
void ask(int x,int y)
{
int k=log(y-x+1)/log(2);
return max(ST[x][k],ST[y-(1<<k)+1][k]);
}
线段树:
//O(logn)修改,O(logn)查询
struct hit{int l,r,w,lazy;}tr[sea*4];
//建树
void build(int k,int l,int r)
{
tr[k].l=l,tr[k].r=r;
if(l==r){tr[k].w=read();return ;}
int mid=(l+r)>>1;
build(lk,l,mid); build(rk,mid+1,r);
tr[k].w=tr[lk].w+tr[rk].w;
}
//标记下传
void down(int k)
{
if(tr[k].lazy)
tr[lk].lazy+=tr[k].lazy; tr[rk].lazy+=tr[k].lazy;
tr[lk].w+=tr[k].lazy*(tr[lk].r-tr[lk].l+1);
tr[rk].w+=tr[k].lazy*(tr[rk].r-tr[rk].l+1);
tr[k].lazy=0;
}
//区间修改(注重优先级,乘法和加法的时候,加法优先)
void alter(int k,int x,int y,int z)
{
int l=tr[k].l,r=tr[k].r;
if(l>=x&&r<=y) {tr[k].w+=z*(r-l+1),tr[k].lazy+=z;return ;}
down(k); int mid=(l+r)>>1;
if(x<=mid) alter(lk,x,y,z); if(y>mid) alter(rk,x,y,z);
tr[k].w=tr[lk].w+tr[rk].w;
}
//区间查询
void ask(int k,int x,int y)
{
int l=tr[k].l,r=tr[k].r;
if(l>=x&&r<=y) {ans+=tr[k].w;return;}
if(tr[k].lazy) down(k);
int mid=(l+r)>>1;
if(x<=mid) ask(lk,x,y); if(y>mid) ask(rk,x,y);
}
树状数组:
//O(logn)修改,O(logn)查询,
over(i,1,n) alter(i,a[i]);
//单点修改
void alter(int x,int d){while(x<=n) c[x]+=d,x+=lowbit(x);}
//前缀和
int sum(int x){int s=0;while(x) s+=c[x],x-=lowbit(x);return s;}
//区间修改(差分)
alter(a[x],z),alter(y+1,-z);
//区间查询
sum(y)-sum(x-1);
//树状数组求逆序对(离散化)
over(i,1,n) a[i]=b[i]=read();
sort(a+1,a+n+1); int len=unique(b+1,b+n+1)-b-1;
over(i,1,n) alter(a[i],1),ans+=i-sum(a[i]);
分块:
//O(sqrt(n))修改+O(sqrt(n))查询
void build()
{
block=sqrt(n); num=n/block+(n%block);
over(i,1,n) belong[i]=(i-1)/block+1;
over(i,1,num) l[i]=(i-1)*block+1,r[i]=i*block;r[num]=n;
}
void alter(int x,int y,int kk,int dd)
{
if(belong[x]==belong[y])
{
over(i,x,y)
{
//块内暴力处理;
}
return ;
}
over(i,x,r[belong[x]]) //块外左边暴力
over(i,belong[x]+1,belong[y]-1) //整块处理(通常数组,函数,vector)
over(i,l[belong[y]],y) //块外右边暴力
return ;
}
//查询类似
字符串:
kmp:(对于一个文章串找有多少个单词串)
int j=0;
over(i,2,lenb)
{
while(j&b[j]!=b[i]) j++;
if(b[j+1]==b[i]) j++: kmp[i]=j;
}
j=0;
ove(i,1,lena)
{
while(j&b[j+1]!=a[i]) j=kmp[j];
if(b[j+1]==a[i]) j++;
if(j==lenb) ans++,j=kmp[j];
}
manacher:( 求最长回文串的长度 )
void manacher()
{
int mid=0,mr=0;
over(i,1,len)
{
if(i<mr) hh[i]=min(hh[(mid<<1)-i],mr-i);
else hh[i]=1;
while(s[hh[i]+i]==s[i-hh[i]]) hh[i]++;
if(i+hh[i]>mr) mr=i+hh[i],mid=i;
ans=max(ans,hh[i]);
}
}