自己的各种模板整理

开个超级大坑,将自己学过的所有模板整理在这里方便复习,不定时更新。

一、数据结构

1、线段树(区间修改,查询最大,最小,和)

早期代码,丑的一B
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define MX 200010
#define mid ((l+r)>>1)
#define ls (id<<1)
#define rs ((id<<1)+1)
#define oo 1423333333333
using namespace std;
typedef long long LL;
typedef struct t_node
{
    int l,r;
    LL mx,mn,sm;
    bool sp,ap;
    LL sn,an;
}treenode;
treenode tree[MX*4];
int n,m;
LL a[MX];
void build(int id,int l,int r)
{
    tree[id].l=l,tree[id].r=r,tree[id].sp=tree[id].ap=tree[id].sn=tree[id].an=0;
    if(l==r)tree[id].mx=tree[id].mn=tree[id].sm=a[l];
    else
	{
        build(ls,l,mid),build(rs,mid+1,r);
        tree[id].mx=max(tree[ls].mx,tree[rs].mx);
        tree[id].mn=min(tree[ls].mn,tree[rs].mn);
        tree[id].sm=tree[ls].sm+tree[rs].sm;
    }
}
void pushdown(int id)
{
    int l=tree[id].l,r=tree[id].r,sn=tree[id].sn,an=tree[id].an;
    if(tree[id].sp)
	{
        tree[ls].sp=1,tree[ls].sn=sn,tree[ls].ap=0,tree[ls].an=0;
        tree[rs].sp=1,tree[rs].sn=sn,tree[rs].ap=0,tree[rs].an=0;
        tree[id].mn=tree[id].mx=sn,tree[id].sm=sn*(r-l+1),tree[id].sp=tree[id].sn=0;
    }
    if(tree[id].ap)
	{
        tree[ls].an+=an,tree[ls].ap=1;
        tree[rs].an+=an,tree[rs].ap=1;
        tree[id].mx+=an,tree[id].mn+=an,tree[id].sm+=an*(r-l+1);
        tree[id].ap=tree[id].an=0;
    }
}
void pushup(int id)
{
    if(tree[id].l==tree[id].r)return;
    tree[id].sm=tree[ls].sm+tree[rs].sm;
    tree[id].mx=max(tree[ls].mx,tree[rs].mx);
    tree[id].mn=min(tree[ls].mn,tree[rs].mn);
}
void add(int id,int ql,int qr,LL x)
{
    pushdown(id);
    int l=tree[id].l,r=tree[id].r;
    if(l>=ql&&r<=qr)
	{
        tree[id].ap=1;
        tree[id].an+=x;
        pushdown(id);
    }
    else if(l>qr||r<ql)return;
    else add(ls,ql,qr,x),add(rs,ql,qr,x),pushup(id);
}
void modify(int id,int ql,int qr,LL x)
{
    pushdown(id);
    int l=tree[id].l,r=tree[id].r;
    if(l>=ql&&r<=qr)
	{
        tree[id].ap=0,tree[id].an=0;
        tree[id].sp=1,tree[id].sn=x;
        pushdown(id);
    }
    else if(l>qr||r<ql)return;
    else modify(ls,ql,qr,x),modify(rs,ql,qr,x),pushup(id);
}
LL qsm(int id,int ql,int qr)
{
    pushdown(id);
    int l=tree[id].l,r=tree[id].r;
    if(l>=ql&&r<=qr)return tree[id].sm;
    else if(l>qr||r<ql)return 0;
    else return qsm(ls,ql,qr)+qsm(rs,ql,qr);
}
LL qmx(int id,int ql,int qr)
{
    pushdown(id);
    int l=tree[id].l,r=tree[id].r;
    if(l>=ql&&r<=qr)return tree[id].mx;
    else if(l>qr||r<ql)return -oo;
    else return max(qmx(ls,ql,qr),qmx(rs,ql,qr));
}
LL qmn(int id,int ql,int qr)
{
    pushdown(id);
    int l=tree[id].l,r=tree[id].r;
    if(l>=ql&&r<=qr)return tree[id].mn;
    else if(l>qr||r<ql)return +oo;
    else return min(qmn(ls,ql,qr),qmn(rs,ql,qr));
}
int main()
{
    char s[100];
    int l,r;LL x;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
	scanf("%lld",&a[i]);
    build(1,1,n);
    for(int i=1;i<=m;i++)
	{
        scanf("%s",s);
        if(s[1]=='d'){scanf("%d%d%lld",&l,&r,&x);add(1,l,r,x);}
        else if(s[1]=='e'){scanf("%d%d%lld",&l,&r,&x);modify(1,l,r,x);}
        else if(s[1]=='u'){scanf("%d%d",&l,&r);printf("%lld\n",qsm(1,l,r));}
        else if(s[1]=='a'){scanf("%d%d",&l,&r);printf("%lld\n",qmx(1,l,r));}
        else if(s[1]=='i'){scanf("%d%d",&l,&r);printf("%lld\n",qmn(1,l,r));}
    }
    return 0;
}

2、主席树(区间第k大)

3、树链剖分(bzoj1036)

4、Splay(bzoj3224普通平衡树)

#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
typedef long long LL;
int read()
{
	char c;int sum=0,f=1;c=getchar();
	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}
int n,opt,x;
int son[maxn][2],fa[maxn],siz[maxn],cnt[maxn],val[maxn],sz,root;
void clear(int x)
{
	son[x][1]=son[x][0]=fa[x]=val[x]=cnt[x]=siz[x]=0;
}
bool getson(int x)
{
	return son[fa[x]][1]==x;
}
void pushup(int x)
{
	if(x)
	{
		siz[x]=cnt[x];
		if(son[x][0]) siz[x]+=siz[son[x][0]];
		if(son[x][1]) siz[x]+=siz[son[x][1]];
	}
}
void rotate(int x)
{
	int y=fa[x],z=fa[y],s=getson(x);
	son[y][s]=son[x][s^1];fa[son[y][s]]=y;
	fa[y]=x;son[x][s^1]=y;fa[x]=z;
	if(z) son[z][y==son[z][1]]=x;
	pushup(y);pushup(x);
}
void splay(int x,int k)
{
	for(int y;(y=fa[x])!=k;rotate(x))
	if(fa[y]!=k)
	rotate(getson(x)==getson(y)?y:x);
	if(!k) root=x;
}
void insert(int x)
{
	if(!root)
	{
		root=++sz;
		son[sz][0]=son[sz][1]=fa[sz]=0;
		val[sz]=x;siz[sz]=cnt[sz]=1;
		return;
	}
	int now=root,f=0;
	while(1)
	{
		if(val[now]==x){cnt[now]++;pushup(now);pushup(f);splay(now,0);break;}
		f=now;now=son[now][val[now]<x];
		if(!now)
		{
			son[++sz][0]=son[sz][1]=0;fa[sz]=f;
			val[sz]=x;cnt[sz]=siz[sz]=1;
			son[f][val[f]<x]=sz;
			pushup(f);splay(sz,0);break;
		}
	}
}
int find(int x)
{
	int ans=0,now=root;
	while(1)
	{
		if(x<val[now])
		now=son[now][0];
		else
		{
			ans+=son[now][0]?siz[son[now][0]]:0;
			if(x==val[now])
			{
				splay(now,0);
				return ans+1;
			}
			ans+=cnt[now];
			now=son[now][1];
		}
	}
}
int findx(int x)
{
	int now=root;
	while(1)
	{
		if(son[now][0] && x<=siz[son[now][0]])
		now=son[now][0];
		else
		{
			int temp=(son[now][0]?siz[son[now][0]]:0)+cnt[now];
			if(x<=temp) return val[now];
			x-=temp;
			now=son[now][1];
		}
	}
}
int pre()
{
	int now=son[root][0];
	while(son[now][1])
	now=son[now][1];
	return now;
}
int nex()
{
	int now=son[root][1];
	while(son[now][0])
	now=son[now][0];
	return now;
}
void del(int x)
{
	find(x);
	if(cnt[root]>1){cnt[root]--;return;}
	if(!son[root][0] && !son[root][1]){clear(root);root=0;return;}
	int oldroot=root;
	if(!son[root][0]){root=son[root][1];fa[root]=0;clear(oldroot);return;}
	if(!son[root][1]){root=son[root][0];fa[root]=0;clear(oldroot);return;}
	splay(pre(),0);
	fa[son[oldroot][1]]=root;
	son[root][1]=son[oldroot][1];
	clear(oldroot);pushup(root);
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)
	{
		opt=read();x=read();
		switch (opt)
		{
			case 1:insert(x);break;
			case 2:del(x);break;
			case 3:printf("%d\n",find(x));break;
			case 4:printf("%d\n",findx(x));break;
 			case 5:insert(x);printf("%d\n",val[pre()]);del(x);break;  
            case 6:insert(x);printf("%d\n",val[nex()]);del(x);break;  
		}
	}
	return 0;
}

5、树状数组

int c[maxn];
void add(int x,int val)
{
	for(;x<=n;x+=x&-x)
	c[x]+=val;
}
int sum(int x)
{
	int ret=0;
	for(;x;x-=x&-x)
	ret+=c[x];
	return ret;
}

6、ST表

二、字符串

1、KMP

2、AC自动机

3、后缀数组

三、图论

1、三种最短路

//floyd
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); 
//spfa
int spfa(int s,int t)
{
	queue<int> q;
	memset(vis,0,sizeof(vis));
	memset(dis,-1,sizeof(dis));
	dis[s]=0,vis[s]=1,q.push(s);
	while(!q.empty())
	{
		int now=q.front();q.pop();
		for(int i=head[now];i;i=nex[i])
		{
			if(dis[to[i]]==-1 || dis[to[i]]>dis[now]+val[i])
			{
				dis[to[i]]=dis[now]+val[i];
				if(!vis[to[i]])
				{
					vis[to[i]]=1;
					q.push(to[i]);
				}
			}
		}
	}
	return dis[t];
}
//dijkstra
struct node{
	int id,dis;
};
bool operator < (node x,node y)
{
	return x.dis>y.dis;
}
priority_queue<node> q;
void dijkstra(int s)
{
	for(int i=1;i<=n;i++)
	dis[i]=inf;
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		node now=q.top();
		q.pop();
		if(vis[now.id])
		continue;
		vis[now.id]=1;
		for(int i=head[now.id];i;i=nextt[i])
		{
			int v=to[i],w=val[i];
            if(now.dis+val[i]<dis[to[i]])
			{
                dis[to[i]]=now.dis+val[i];
                q.push((node){to[i],dis[to[i]]});
            }
		}
	}
}

2、拓扑排序

3、二分图匹配(最大匹配,最优匹配)

//最优匹配——KM算法
#include<bits/stdc++.h>
#define inf 99999999
#define maxn 305
using namespace std;
typedef long long LL;
int read()
{
    char c;int sum=0,f=1;c=getchar();
    while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
    return sum*f;
}
int n;
int l[maxn],r[maxn];
int visl[maxn],visr[maxn];
int slack[maxn],a[maxn][maxn];
int match[maxn];
bool dfs(int x)
{
    visl[x]=1;
    for(int i=1;i<=n;i++)
    {
        if(visr[i]) continue;
        int ret=l[x]+r[i]-a[x][i];
        if(ret==0)
        {
            visr[i]=1;
            if(!match[i] || dfs(match[i]))
            {
                match[i]=x;
                return true;
            }
        }
        else slack[i]=min(slack[i],ret);
    }
    return false;
}
int KM()
{
    memset(match,0,sizeof(match));
    memset(r,0,sizeof(r));
    for(int i=1;i<=n;i++)
    {
        l[i]=a[i][1];
        for(int j=2;j<=n;j++)
        l[i]=max(l[i],a[i][j]);
    }
    for(int i=1;i<=n;i++)
    {
        fill(slack+1,slack+n+1,inf);
        while(1)
        {
            memset(visl,0,sizeof(visl));
            memset(visr,0,sizeof(visr));
            if(dfs(i)) break;
            int d=inf;
            for(int j=1;j<=n;j++)
            if(!visr[j]) d=min(d,slack[j]);
            for(int j=1;j<=n;j++)
            {
                if(visl[j]) l[j]-=d;
                if(visr[j]) r[j]+=d;
                else slack[i]-=d;
            }
            
        } 
    }
    int ret=0;
    for(int i=1;i<=n;i++)
    ret+=a[match[i]][i];
    return ret;
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        a[i][j]=read();
        printf("%d\n",KM());
    }
    return 0;
}

4、最小生成树

/*
最小生成树-Kruskal 
*/
#include<bits/stdc++.h>
#define maxm 200010
using namespace std;
typedef long long LL;
int read()
{
	char c;int sum=0,f=1;c=getchar();
	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}
int fa[5005],n,m;
struct node{
	int u,v,w;
}a[maxm];
int cmp(node a,node b)
{
	return a.w<b.w;
}
void init()
{
	for(int i=1;i<=n;i++)
	fa[i]=i;
}
int getfa(int x)
{
	return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
bool unio(int x,int y)
{
	int xx=getfa(x),yy=getfa(y);
	if(xx!=yy)
	{
		fa[yy]=xx;
		return true;
	}
	return false;
}
LL ans;int num;
int main()
{
	n=read();m=read();
	init();
	for(int i=1;i<=m;i++)
	a[i].u=read(),a[i].v=read(),a[i].w=read();
	sort(a+1,a+1+m,cmp);
	for(int i=1;i<=m;i++)
	{
		if(unio(a[i].u,a[i].v))
		{
			num++;
			ans+=a[i].w;
		}
		if(num==n-1)
		break;
	}
	cout<<ans<<endl;
	return 0;
}

5、倍增求LCA

6、强连通分量(tarjan)

7、并查集

int fa[maxn];
void init()
{
	for(int i=1;i<=n;i++)
	fa[i]=i;
}
int getfa(int x)
{
	return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
void unio(int x,int y)
{
	int xx=getfa(x),yy=getfa(y);
	if(xx!=yy)
		fa[yy]=xx;
}

8、最大流(dinic)

#include<bits/stdc++.h>
#define maxn 10005
#define maxm 200005
#define inf 0x7fffffff
using namespace std;
typedef long long LL;
int read()
{
	char c;int sum=0,f=1;c=getchar();
	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}
int n,m,s,t,cnt=1;
int head[maxn],to[maxm],nex[maxm],cap[maxm];
void add(int u,int v,int w)
{
	to[++cnt]=v;cap[cnt]=w;nex[cnt]=head[u];head[u]=cnt;
}
int level[maxn],iter[maxn];
void bfs(int s)
{
	memset(level,-1,sizeof(level));
	queue<int> q;
	q.push(s);level[s]=0;
	while(!q.empty())
	{
		int now=q.front();q.pop();
		for(int i=head[now];i;i=nex[i])
		if(cap[i]>0 && level[to[i]]==-1)
		level[to[i]]=level[now]+1,q.push(to[i]);
	}
}
int dfs(int now,int t,int flow)
{
	if(now==t) return flow;
	for(int &i=iter[now];i;i=nex[i])
	{
		if(cap[i]>0 && level[now]<level[to[i]])
		{
			int res=dfs(to[i],t,min(flow,cap[i]));
			if(res>0)
			{
				cap[i]-=res;
				cap[i^1]+=res;
				return res;
			}
		}
	}
	return 0;
}
int dinic(int s,int t)
{
	int flow=0;
	for(;;)
	{
		bfs(s);
		if(level[t]==-1) return flow;
		for(int i=1;i<=n;i++)
		iter[i]=head[i];
		int f;
		while((f=dfs(s,t,inf))>0)
		flow+=f;
	}
}
int main()
{
	n=read();m=read();s=read();t=read();
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read(),w=read();
		add(u,v,w);add(v,u,0);
	}
	printf("%d\n",dinic(s,t));
	return 0;
}

9、最小费用流(spfa)

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define maxn 5005
using namespace std;
typedef long long LL;
int read()
{
	char c;int sum=0,f=1;c=getchar();
	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}
struct node{
	int to,cap,cost,rev;
};
int n,m,s,t;
int dis[maxn],prevv[maxn],preve[maxn];
bool vis[maxn];
vector<node> edge[maxn];
void add(int u,int v,int cap,int cost)
{
	edge[u].push_back((node){v,cap,cost,edge[v].size()});
	edge[v].push_back((node){u,0,-cost,edge[u].size()-1});
}
int res,flow;
void min_cost_flow(int s,int t,int f)
{
	while(f>0)
	{
		memset(dis,-1,sizeof(dis));
		memset(vis,0,sizeof(vis));
		queue<int> q;
		dis[s]=0;q.push(s);vis[s]=1;
		while(!q.empty())
		{
			int now=q.front();q.pop();vis[now]=0;
			for(int i=0;i<edge[now].size();i++)
			{
				node &nex=edge[now][i];
				if(nex.cap>0 && (dis[nex.to]==-1 || dis[nex.to]>dis[now]+nex.cost))
				{
					dis[nex.to]=dis[now]+nex.cost;
					prevv[nex.to]=now;
					preve[nex.to]=i;
					if(!vis[nex.to])
					{
						vis[nex.to]=1;
						q.push(nex.to);
					}
				}
			}
		}
		if(dis[t]==-1) return;
		int d=f;
		for(int i=t;i!=s;i=prevv[i])
			d=min(d,edge[prevv[i]][preve[i]].cap);
		f-=d;
		flow+=d;
		res+=d*dis[t];
		for(int i=t;i!=s;i=prevv[i])
		{
			node &e=edge[prevv[i]][preve[i]];
			e.cap-=d;
			edge[i][e.rev].cap+=d;
		}
	}
}
int main()
{
	n=read();m=read();s=read();t=read();
	for(int i=1;i<=m;i++)
	{
		int u=read(),v=read(),cap=read(),cost=read();
		add(u,v,cap,cost);
	}
	min_cost_flow(s,t,inf);
	printf("%d %d\n",flow,res);
	return 0;
}

四、数学

1、线性筛素数

int n,m;
bool a[maxn];
int prime[670005],tot;
void shai()
{
	a[1]=1;
	for(int i=2;i<n;i++)
	{
		if(!a[i])
		prime[++tot]=i;
		for(int j=1;j<=tot && i*prime[j]<n;j++)
		{
			a[i*prime[j]]=1;
            if(!(i%prime[j]))
            break;
		}
	}
}

2、高斯消元

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int read()
{
	char c;int sum=0,f=1;c=getchar();
	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}
const double eps=1e-7;
int n;
double a[maxn][maxn];
double abs(double x)
{
	return now>0?now:-now;
}
bool gauss()
{
	for(int i=1;i<=n;i++)
	{
		int row=i;
		for(int j=i+1;j<=n;j++)
		if(abs(a[j][i])>abs(a[row][i])) row=j;
		if(abs(a[row][i])<eps) return false;
		if(row!=i) for(int j=1;j<=n+1;j++)swap(a[row][j],a[i][j]);
		for(int j=i+1;j<=n;j++)
		{
			double temp=a[j][i]/a[i][i];
			for(int k=i;k<=n+1;k++)	a[j][k]-=temp*a[i][k]; 
		}
	}
	for(int i=n;i>=1;i--)
	{
		double ans=a[i][n+1]=a[i][n+1]/a[i][i];
		for(int j=i-1;j>=1;j--) a[j][n+1]-=(ans*a[j][i]);
	} 
	return true;
}
int main()
{
	n=read();
	for(int i=1;i<=n;i++)
	for(int j=1;j<=n+1;j++)
	{
		int x=read();
		a[i][j]=1.0*x;
	}
	if(!gauss()) 
	{
		printf("No Solution\n");
		return 0;
	}
	for(int i=1;i<=n;i++)
	printf("%.2lf\n",a[i][n+1]);
	return 0;
}

3、gcd与ex-gcd

int gcd(int a,int b)
{
	return b==0?a:gcd(b,a%b);
}
int ex_gcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;y=0;
		return a;
	}
	ex_gcd(b,a%b,y,x);
	y-=(a/b)*x; 
}

4、中国剩余定理

int ex_gcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	else
	{
		ex_gcd(b,a%b,y,x);
		y-=(a/b)*x;
	}
}
int crt()
{
	int sum=1,ans=0;
	for(int i=1;i<=n;i++)
	sum*=m[i];
	for(int i=1;i<=n;i++)
	{
		int x,y;
		int mi=sum/m[i];
		ex_gcd(mi,m[i],x,y);
		ans+=(mi*x*a[i])%sum;
	}
	ans=(ans+sum)%sum;
}

5、Miller-Rabin 素性测试

6、Pollard Rho分解因数

7、递推求欧拉函数

8、矩阵乘法

9、Lucas定理

猜你喜欢

转载自blog.csdn.net/qq_39791208/article/details/79146590