我的代码模板库
我的代码模板库
目录
树型结构
数据结构
网络流
数学 数论
LCA问题
ST表
字符串
一、准备阶段
1.Getdit配置
#!/bin/sh
dir=$GEDIT_CURRENT_DOCUMENT_DIR
nam=$GEDIT_CURRENT_DOCUMENT_NAME
gnome-terminal --working-directory=$dir -x bash -c "g++ $nam -g -o te;
echo 'DONE';./te;echo;echo 'END';read"
2.开始模板
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define rg register int
#define ll long long
#define RG register
#define il inline
using namespace std;
il int gi() {
rg x=0,o=0;RG char ch=getchar();
while(ch!='-'&&(ch<'0'||'9'<ch)) ch=getchar();
if(ch=='-') o=1,ch=getchar();
while('0'<=ch&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return o?-x:x;
}
int main() {
return 0;
}
二、代码库
树型结构
1.加边函数
struct Edge{ int to,nxt; }e[SZ];
int Ehead[SZ],Ecnt=2;
il void Eadd(rg u,rg v) {
e[Ecnt]=(Edge){v,Ehead[u]};
Ehead[u]=Ecnt++;
e[Ecnt]=(Edge){u,Ehead[v]};
Ehead[v]=Ecnt++;
}
2.树剖 (树剖+线段树)
define lson (rt<<1)
define rson (rt<<1|1)
void dfs1(rg u,rg ff) {
fa[u]=ff,dep[u]=dep[ff]+1,siz[u]=1;
for(rg v,i=Ehead[u]; i; i=e[i].nxt) {
v=e[i].to; if(v==ff) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void dfs2(rg u,rg tp) {
top[u]=tp,id[u]=++cnt,rid[cnt]=u;
if(!son[u]) return;
dfs2(son[u],tp);
for(rg v,i=Ehead[u]; i; i=e[i].nxt) {
v=e[i].to;
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
struct Segtree{ int l,r;ll len,sum,mark; }tr[400040];
il void Seg_debug() {
for(rg i=1;i<=n*3;++i)
cout<<tr[i].l<<' '<<tr[i].r<<' '<<tr[i].len<<' '<<tr[i].sum<<' '<<tr[i].mark<<endl;
}
il void pushup(rg rt) {
tr[rt].sum=(tr[lson].sum+tr[rson].sum)%mo;
}
il void pushdown(rg rt) {
if(tr[rt].mark) {
ll mark=tr[rt].mark;
tr[lson].mark+=mark;
tr[rson].mark+=mark;
tr[lson].sum=(tr[lson].sum+mark*tr[lson].len)%mo;
tr[rson].sum=(tr[rson].sum+mark*tr[rson].len)%mo;
tr[rt].mark=0;
}
}
void build(rg rt,rg l,rg r) {
tr[rt].l=l,tr[rt].r=r,tr[rt].len=r-l+1;
if(l==r) {tr[rt].sum=w[rid[l]]%mo;return;}
rg mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(rt);
}
void modify(rg rt,rg L,rg R,ll x) {
rg l=tr[rt].l,r=tr[rt].r;
if(L<=l&&r<=R) {
tr[rt].sum=(tr[rt].sum+tr[rt].len*x)%mo;
tr[rt].mark+=x;
return;
}
pushdown(rt);
rg mid=l+r>>1;
if(L<=mid) modify(lson,L,R,x);
if(R>mid) modify(rson,L,R,x);
pushup(rt);
}
ll query(rg rt,rg L,rg R) {
rg l=tr[rt].l,r=tr[rt].r;
if(L<=l&&r<=R) return tr[rt].sum;
pushdown(rt);
rg mid=l+r>>1;RG ll ret=0;
if(L<=mid) ret=(ret+query(lson,L,R))%mo;
if(R>mid) ret=(ret+query(rson,L,R))%mo;
return ret;
}
il ll asksum(rg u,rg v) { // 查询 u 到 v 之间的点权和
RG ll Ans=0;
while(top[u]!=top[v]) { // 注意这里是重链顶端深度大的先跳 而不是这个点深度大的先
if(dep[top[u]]<dep[top[v]]) swap(u,v);<span id="des">destination</span>
Ans=(Ans+query(1,id[top[u]],id[u]))%mo;
u=fa[top[u]];
}
if(id[u]>id[v]) swap(u,v);
Ans=(Ans+query(1,id[u],id[v]))%mo;
return Ans;
}
il void addsum(rg u,rg v,ll x) { // 给从u到v路径上的点+x
while(top[u]!=top[v]) {
if(dep[top[u]]<dep[top[v]]) swap(u,v);
modify(1,id[top[u]],id[u],x);
u=fa[top[u]];
}
if(id[u]>id[v]) swap(u,v);
modify(1,id[u],id[v],x);
}
2.LCT Link-Cut Tree
struct Splaytree{ int rev,sum,val,fa,ch[2]; }tr[SZ];
il void pushup(rg x) {
tr[x].sum=tr[tr[x].ch[0]].sum^tr[tr[x].ch[1]].sum^tr[x].val;
}
il void pushdown(rg x) {
if(tr[x].rev) {
swap(tr[x].ch[0],tr[x].ch[1]);
tr[tr[x].ch[0]].rev^=1;
tr[tr[x].ch[1]].rev^=1;
tr[x].rev=0;
}
}
il bool isroot(rg x) {
return tr[tr[x].fa].ch[0]!=x && tr[tr[x].fa].ch[1]!=x;
}
il void rotate(rg x) {
rg y=tr[x].fa,z=tr[y].fa;
rg k=(tr[y].ch[1]==x);
if(!isroot(y)) tr[z].ch[y==tr[z].ch[1]]=x;tr[x].fa=z;
tr[y].ch[k]=tr[x].ch[k^1],tr[tr[x].ch[k^1]].fa=y;
tr[x].ch[k^1]=y,tr[y].fa=x;
pushup(y);
}
il void splay(rg x) {
stk[top=1]=x;
for(rg i=x; !isroot(i); i=tr[i].fa) stk[++top]=tr[i].fa;
for(rg i=top;i;--i) pushdown(stk[i]);
while(!isroot(x)) {
rg y=tr[x].fa,z=tr[y].fa;
if(!isroot(y)) (tr[y].ch[0]==x)^(tr[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
pushup(x);
}
il void access(rg x) {
for(rg y=0; x; y=x,x=tr[x].fa)
splay(x),tr[x].ch[1]=y,pushup(x);
}
il void makeroot(rg x) {
access(x),splay(x),tr[x].rev^=1;
}
il int findroot(rg x) {
access(x),splay(x);
while(tr[x].ch[0]) x=tr[x].ch[0];
return x;
}
il void split(rg x,rg y) { // 让xy到一条链上并且y在根x在底
makeroot(x),access(y),splay(y);
}
il void cut(rg x,rg y) {
split(x,y);
if(tr[y].ch[0]==x) tr[y].ch[0]=tr[x].fa=0;
}
il void link(rg x,rg y) {
makeroot(x),tr[x].fa=y;
}
数据结构
1.Splay
#define lson tr[x].ch[0]
#define rson tr[x].ch[1]
il void pushup(rg x) {
tr[x].siz=tr[lson].siz+tr[rson].siz+tr[x].cnt;
}
il void pushdown(rg x) {
if(tr[x].tag) {
tr[lson].tag^=1,tr[rson].tag^=1;
tr[x].tag=0,swap(lson,rson);
}
}
il void rotate(rg x) {
rg y=tr[x].fa,z=tr[y].fa;
rg k=tr[y].ch[1]==x;
tr[z].ch[tr[z].ch[1]==y]=x,tr[x].fa=z;
tr[y].ch[k]=tr[x].ch[k^1],tr[tr[x].ch[k^1]].fa=y;
tr[x].ch[k^1]=y,tr[y].fa=x;
}
il void splay(rg x,rg goal) {
while(tr[x].fa!=goal) {
rg y=tr[x].fa,z=tr[y].fa;
if(z!=goal)
(tr[y].ch[0]==x)^(tr[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!goal) root=x;
}
il int newnode() {
if(!top) return ++tot;
return stk[top--];
}
il void insert(rg x) {
rg u=root,fa=0;
while(u&&x!=tr[u].val) fa=u,u=tr[u].ch[x>tr[u].val];
u=newnode();
if(fa) tr[fa].ch[x>tr[fa].val]=u;
tr[u]=(Splaytree){fa,{0,0},x};
splay(u,0);
}
il int k_th(rg x) {
rg u=root;
if(tr[u].siz<x) return 0;
while(666) {
pushdown(u);
rg y=tr[u].ch[0];
if(x>tr[y].siz+tr[u].cnt) {
x-=tr[y].siz+tr[u].cnt;
u=tr[u].ch[1];
}
else if(x<=tr[y].siz) u=y;
else return tr[u].val;
}
}
il void find(rg x) {
rg u=root; if(!u) return;
while(tr[u].ch[x>tr[u].val]&&x!=tr[u].val) u=tr[u].ch[x>tr[u].val];
splay(u,0);
}
il int getnext(rg x,rg type) { // 前驱后继 - 不严格
find(x);
if(tr[root].val<=x&&!type) return root;
if(tr[root].val>=x&&type) return root;
rg u=tr[root].ch[type];
while(tr[u].ch[type^1]) u=tr[u].ch[type^1];
return u;
}
il int delnext(rg x,rg type) { // 前驱后继 - 严格
if(tr[root].val<x&&!type) return root;
if(tr[root].val>x&&type) return root;
rg u=tr[root].ch[type];
while(tr[u].ch[type^1])
u=tr[u].ch[type^1];
return u;
}
il void del(rg x) {
find(x);
rg lnum=delnext(x,0);
rg rnum=delnext(x,1);
splay(lnum,0),splay(rnum,lnum);
stk[++top]=tr[rnum].ch[0];
tr[rnum].ch[0]=0;
}
2.主席树
struct Tree {
int l,r,sum;
}tr[SZ*25];
#define lson tr[rt].l
#define rson tr[rt].r
int tot,Ed[SZ];
il void Chair_debug() {
for(rg i=1;i<=tot;++i)
printf("%d %d %d \n",tr[i].l,tr[i].r,tr[i].sum);
}
il void build(int &rt,rg l,rg r) { //用 & 是为了方便改左右儿子
rt=++tot;
if(l==r) return;
rg mid=l+r>>1;
build(lson,l,mid);
build(rson,mid+1,r);
}
il void update(int &rt,rg last,rg l,rg r,rg val) {
rt=++tot;
lson=tr[last].l;rson=tr[last].r;
tr[rt].sum=tr[last].sum+1; // 加1是因为 沿路单点修改 出现次数肯定是 +1
if(l==r) return;
rg mid=l+r>>1;
if(val<=mid) update(lson,tr[last].l,l,mid,val); // 要加等号!!!
else update(rson,tr[last].r,mid+1,r,val);
// 相当于 除了新加进来的数,其他的部分都共用
}
il int query(rg to,rg from,rg l,rg r,rg k) {
if(l==r) return l;
rg num=tr[tr[to].l].sum-tr[tr[from].l].sum;
rg mid=l+r>>1;
if(k<=num) return query(tr[to].l,tr[from].l,l,mid,k);
else return query(tr[to].r,tr[from].r,mid+1,r,k-num);
}
// 主席树 Ed[i] 存1到i前缀所建线段树的根
// 每颗线段树的节点作用不同于普通的线段树
// 它保存的是 一个数的出现次数
// 注意这个数是已经排好了序的
3.左偏树
#define lson ch[x][0]
#define rson ch[x][1]
int ch[SZ][2],val[SZ],dis[SZ];
int merge(rg x,rg y) {
if(!x||!y) return x+y;
if(val[x]>val[y]||(val[x]==val[y]&&x>y)) swap(x,y);
rson=merge(rson,y);fa[rson]=x;
if(dis[lson]<dis[rson]) swap(lson,rson);
dis[x]=dis[rson]+1;
return x;
}
网络流
1.最大流
Ecnt=2 // 这里要特别说明 , 因为边的初始标号一定要是2
int lev[SZ],cur[SZ];
queue <int> Q;
il bool bfs() {
for(rg i=1;i<=n+1;++i) lev[i]=-1;
while(!Q.empty()) Q.pop();
Q.push(s);lev[s]=0;
while(!Q.empty()) {
rg u=Q.front();Q.pop();
for(rg i=Ehead[u]; i; i=e[i].nxt)
if(e[i].w>0&&lev[e[i].to]<0) {
lev[e[i].to]=lev[u]+1;
Q.push(e[i].to);
}
}
if(lev[t]>0) return 1;
return 0;
}
int dfs(int u,int f) {
if(u==t||f==0) return f;
for(int i=Ehead[u];i;i=e[i].nxt) {
rg di=0,v=e[i].to;
if(lev[v]==lev[u]+1 && e[i].w>0)
if(di=dfs(v,min(f,e[i].w))) {
e[i].w-=di;
e[i^1].w+=di;
return di;
}
}
return 0;
}
il int Dinic() {
int Ans=0,di;
while(bfs()) while((di=dfs(s,INF))&&(Ans+=di));
}
2.费用流
// pv流的上一个点
// pe是连接u和pv的边
bool spfa() {
memset(dis,63,sizeof(dis));
dis[s]=0;Q.push(s);
while (!Q.empty()) {
int u=Q.front();Q.pop();
for (int v,i=Ehead[u]; i; i=e[i].nxt) {
v=e[i].to;
if(e[i].w && dis[v]>dis[u]+e[i].cost) {
dis[v]=dis[u]+e[i].cost,pe[v]=e,pv[v]=u;
if (!vis[v]) vis[v]=1,Q.push(v);
}
}
vis[u]=0;
}
return dis[t]<dis[0];
}
int main() {
while (spfa()) {
int sum=inf;
for (int i=t;i!=s;i=pv[i]) sum=min(sum,e[pe[i]].w);
flow+=sum;
for (int i=t;i!=s;i=pv[i]) e[pe[i]].w-=sum,e[pe[i]^1].w+=sum,ans+=sum*e[pe[i]].cost;
}
}
3.匈牙利算法
il int hung()
{
rg Ans=0;
memset(vis,-1,sizeof(vis));
memset(mat,-1,sizeof(mat));
for(rg i=1;i<=n;++i){
if(mat[i]!=-1) continue;
while(!Q.empty()) Q.pop();
Q.push(i),pre[i]=-1,flg=0;
while(!Q.empty() && !flg) {
rg u=Q.front();Q.pop();
for(rg j=Ehead[u];(j)&&(!flg);j=e[j].nxt) {
rg v=e[j].to;
if(vis[v]==i) continue;
vis[v]=i;
if(mat[v]>=0) pre[mat[v]]=u,Q.push(mat[v]);
else {
flg=1;
rg a=u,b=v;
while(a!=-1) {
rg c=mat[a];
mat[a]=b;
mat[b]=a;
a=pre[a];
b=c;
}
}
}
}
if(mat[i]!=-1) Ans++;
}
return Ans;
}
数学 数论
1.高斯消元
il void Gauss() {
for(rg i=1; i<=n; ++i) {
now=i;
for(rg j=i+1; j<=n; ++j)
if(fabs(f[now][i])<fabs(f[j][i]))
now=j;
for(rg j=i; j<=n+1; ++j)
swap(f[now][j],f[i][j]);
if(!f[i][i]){puts("No Solution");exit(0);}
for(rg j=i+1; j<=n+1; ++j) f[i][j]/=f[i][i];
f[i][i]=1.0;
for(rg j=i+1; j<=n; ++j) {
for(rg k=i+1; k<=n+1; ++k)
f[j][k]-=f[j][i]*f[i][k]; // 理解!
f[j][i]=0.0;
}
}
for(rg i=n; i>=1; --i) {
for(rg j=i+1; j<=n; ++j) {
f[i][n+1]-=f[i][j]*f[j][n+1];
f[i][j]=0;
}
f[i][n+1]/=f[i][i];
f[i][i]=1;
}
}
2.FFT
struct Complex {
ldb r,i;
Complex(){} Complex(ldb a,ldb b):r(a),i(b){}
il Complex operator+(const Complex B)const {return Complex(r+B.r,i+B.i);}
il Complex operator-(const Complex B)const {return Complex(r-B.r,i-B.i);}
il Complex operator*(const Complex B)const {return Complex(r*B.r-i*B.i,r*B.i+i*B.r);}
};
Complex X,Y,a[SZ],b[SZ];
il void FFT(Complex *a,int x) {
for(rg i=0; i<n; ++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(rg i=1; i<n; i<<=1) {
Complex wn=(Cos(pi/i),x*sin(pi/i));
for(rg j=0; j<n; j+=(i<<1)) {
Complex w(1,0);
for(rg k=0;k<i;++k,w=w*wn) {
X=a[j+k],Y=a[i+j+k]*w;
a[j+k]=X+Y,a[i+j+k]=X-Y;
}
}
}
if(x==-1) for(rg i=0; i<n; ++i) a[i].r=a[i].r/n;
}
int main() {
m+=n;for(n=1;n<=m;n<<=1) ++l;
for(rg i=0;i<n;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
FFT(a,1);FFT(b,1);
for(rg i=0;i<=n;++i) a[i]=a[i]*b[i];
FFT(a,-1);
for(rg i=0;i<=m;++i) printf("%d ",(int)(a[i].r+0.5));
}
3.扩展欧几里德
int exgcd(int a,int b,int &x,int &y) {
if(!b){x=1,y=0;}
else{exgcd(b,a%b,y,x);y-=a/b*x;}
}
il int inv() {
exgcd(a,b,x,y);
return (x+b)%b;
}
LCA问题
1.RMQ+LCA
int par[SZ][50],dep[SZ];
void dfs(int u,int fa) {
dep[u]=dep[fa]+1;
par[u][0]=fa;
for(rg i=1;i<=20;i++) par[u][i]=par[par[u][i-1]][i-1];
for(rg i=Ehead[u];i;i=e[i].nxt) if(e[i].to!=fa) dfs(e[i].to,u);
}
il int LCA_RMQ(int u,int v) {
if(dep[u]>dep[v]) swap(u,v);
for(rg i=0;i<=20;++i)
if(((dep[v]-dep[u])>>i)&1)
v=par[v][i];
if(u==v) return u;
for(rg i=20;i>=0;--i)
if(par[u][i]!=par[v][i])
{
u=par[u][i];
v=par[v][i];
}
return par[u][0];
}
2.tarjan+LCA
int vis[SZ];
inline void tarjan(int u)
{
vis[u]=1;
for(int i=Ehead[u];i;i=e[i].nxt) {
int v=e[i].to;
if(vis[v]) continue;
tarjan(v);
Union(u,v);
}
for(int i=Qhead[u];i;i=q[i].nxt)
if(vis[q[i].to]==2) {
q[i].ans=find_fa(q[i].to);
if(i&1) q[i+1].ans=q[i].ans;
else q[i-1].ans=q[i].ans;
}
vis[u]=2;
}
ST表
il void pre() {
for(rg j=1;(1<<j)<=n;++j)
for(rg i=1;i+(1<<j)-1<=n;++i)
R[i][j]=max(R[i][j-1],R[i+(1<<(j-1))][j-1]);
}
il int ask() {
rg k=log2(r-l+1);
return max(R[l][k],R[r-(1<<k)+1][k]);
}
字符串
1.AC 自动机
il void init(rg x) {
memset(tr[x].ch,0,sizeof(tr[x].ch));
tr[x].fail=tr[x].end=0;
}
il void build(string s,rg Num) {
rg l=s.length(),now=0;
for(rg i=0;i<l;++i) {
if(!tr[now].ch[s[i]-'a']) {
tr[now].ch[s[i]-'a']=++cnt;
init(cnt);
}
now=tr[now].ch[s[i]-'a'];
}
tr[now].end=Num;
}
queue <int> Q;
il void getfail() {
tr[0].fail=0;
while(!Q.empty()) Q.pop();
for(rg i=0;i<26;++i)
if(tr[0].ch[i]) {
tr[tr[0].ch[i]].fail=0;
Q.push(tr[0].ch[i]);
}
while(!Q.empty()) {
rg u=Q.front();Q.pop();
for(rg i=0;i<26;++i) {
if(tr[u].ch[i]) {
tr[tr[u].ch[i]].fail=tr[tr[u].fail].ch[i];
Q.push(tr[u].ch[i]);
}
else tr[u].ch[i]=tr[tr[u].fail].ch[i];
}
}
}
il void query() {
cin>>s[0];
rg l=s[0].length(),now=0,fa;
for(rg i=0;i<l;++i) {
now=tr[now].ch[s[0][i]-'a'];fa=-1;
for(rg j=now;j;fa=j,j=tr[j].fail) {
if(!tr[j].end&&fa!=-1) tr[fa].fail=tr[j].fail;
++ans[tr[j].end].num;
}
}
}
2.KMP
il void Get_Next() {
rg i=0,j=-1;nxt[0]=-1;
while(i<s2.size()) {
if(j==-1||s2[i]==s2[j]) nxt[++i]=++j;
else j=nxt[j];
}
}
il void KMP() {
rg i=0,j=0;
while(i<s1.size()) {
if(j==-1||s1[i]==s2[j]) ++i,++j;
else j=nxt[j];
if(j==s2.size()) j=nxt[j];
}
}