模板大全

模板整理

自己整理的模板,能力有限只有这么多:

>> 数学专题

exgcd

#include<iostream>
using namespace std;
int ex_gcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1,y=0;
		return a;
	}
	int k=a/b;
	int g=ex_gcd(b,a%b,x,y);
	x-=k*y,swap(x,y);
	return g;
}
int main()
{
	int a,b,x=0,y=0;
	cin>>a>>b;
	cout<<"gcd="<<ex_gcd(a,b,x,y)<<endl;
	cout<<a<<"*"<<x<<"+"<<b<<"*"<<y<<"="<<ex_gcd(a,b,x,y);
	return 0;
}

扩展CRT

#include<bits/stdc++.h>
#define N 100005
#define ll long long
using namespace std;
ll n,m[N],c[N];
map<ll,bool> vis;
ll gcd(ll a,ll b) {return b==0?a:gcd(b,a%b);}
ll exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0)
	{
		x=1,y=0;
		return a;
	}
	ll g=exgcd(b,a%b,x,y);
	x-=a/b*y,swap(x,y);
	return g;
}
ll inv(ll a,ll b)
{
	ll x,y;
	exgcd(a,b,x,y);
	while(x<0)	x+=b;
	return x;
}
ll mul(ll a,ll b,ll mod)
{
	ll ans=0;
	while(b>0)
	{
		if(b&1)
			ans=(ans+a)%mod;
		a=(a+a)%mod,b>>=1;
	}
	return ans;
}
int main()
{
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&m[i],&c[i]);
	if(c[2]<c[1])
		swap(c[1],c[2]),swap(m[1],m[2]);
	ll C,M,d=gcd(m[1],m[2]),g=m[2]/d;
	C=mul(inv(m[1]/d,g),(c[2]-c[1])/d,g)*m[1]+c[1],M=m[1]/d*m[2];
	for(int i=3;i<=n;i++)
	{
		if(m[i]==1 || C%m[i]==c[i] || vis[m[i]])
			continue;
		vis[m[i]]=1;
		if(c[i]>C)
			swap(c[i],C),swap(m[i],M);
		d=gcd(M,m[i]),g=M/d;
		C=mul(inv(m[i]/d,g),(C-c[i])/d,g)*m[i]+c[i];
		M=M/d*m[i];
		C=(C%M+M)%M;
	}
	cout<<C;
	return 0;
}

中国剩余定理

#include<iostream>
using namespace std;
long long n,ans,M=1,G=1,a[15],b[15],c[15],d[15];
long long gcd(long long a,long long b){
	return b==0?a:gcd(b,a%b);
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
	if(b==0)
	{
		x=1,y=0;
		return a;
	}
	long long g=exgcd(b,a%b,x,y);
	x-=a/b*y; swap(x,y);
	return g;
}
long long mul(long long x,long long y,long long mod)
{
	long long now=0;
	while(y)
	{
		if(y&1) now=(now+x)%mod;
		x=(x<<1)%mod,y>>=1;
	}
	return now;
}
void crt()
{
	for(int i=1;i<=n;i++)
		M=M*b[i];
	G=gcd(b[1],b[2]);
	for(int i=3;i<=n;i++)
		G=gcd(G,b[i]);
	M/=G;
	for(int i=1;i<=n;i++)
	{
		long long x,y,m=M/b[i];
		exgcd(m,b[i],x,y);
		if(M>1000000)
			ans+=(mul(mul(x,m,M),a[i],M)+M)%M;
		else
			ans+=(x*m*a[i])%M;
	}
	if(ans<0)	ans+=M;
	ans%=M;
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
		cin>>b[i];
	crt(),cout<<ans;
	return 0;
}

矩阵快速幂

#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
struct marix{
	int n,m;
	int a[105][105];
	marix(){n=m=0,memset(a,0,sizeof(a));}
	marix(int N,int M,int val)
	{
		n=N,m=M;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				a[i][j]=val;
	}
	marix mul(marix nex)
	{
		int N=nex.n,M=nex.m;
		if(m!=N)
		{
			cout<<"error!\n";
			marix NullMarix;
			return NullMarix;
		}
		marix ans;
		ans.n=n,ans.m=M;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=M;j++)
				for(int k=1;k<=m;k++)
					ans.a[i][j]+=a[i][k]*nex.a[k][j];
		return ans;
	}
}a;
marix kuaisu_mi(marix x,int b)
{
	marix ans(x.n,x.m,0);
	for(int i=1;i<=x.n;i++)
		ans.a[i][i]=1;
	while(b!=0)
	{
		if(b&1)	ans=ans.mul(x);
		x=x.mul(x);
		b>>=1;
	}
	return ans;
}
int main()
{
	int x;
	cin>>a.n>>a.m;
	for(int i=1;i<=a.n;i++)
		for(int j=1;j<=a.m;j++)
			cin>>a.a[i][j];
	cin>>x;
	a=kuaisu_mi(a,x);
	for(int i=1;i<=a.n;i++)
	{
		for(int j=1;j<=a.m;j++)
			cout<<a.a[i][j]<<" ";
		cout<<endl;
	}
	return 0;
}

欧拉筛

#include<iostream>
using namespace std;
int cnt,prime[100005];
bool vis[100000005];
void shuffle(int n)
{	
	for(int i=2;i<=n;i++)
	{
		if(!vis[i])
			prime[++cnt]=i;
		for(int j=1;j<=cnt && prime[j]*i<=n;j++)
		{
			vis[prime[j]*i]=1;
			if(i%prime[j]==0)
				break;
		}
	}
}
int main()
{
	int n;
	cin>>n;
	shuffle(n);
	cout<<cnt;
	return 0;
}

>> 图论专题

SPFA

#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
struct nod{
	int to,val;
};
int q[100005];
vector<nod> edge[100005];
int d[100005],vis[100005],n,m;
void addedge(int i,int j,int w)
{
	edge[i].push_back((nod){j,w});
	edge[j].push_back((nod){i,w});
}
int spfa(int s,int e)
{
	memset(d,-1,sizeof(d));
	memset(vis,0,sizeof(vis));
	int head=1,tail=1;
	q[head]=s,d[s]=0;
	while(head<=tail)
	{
		int now=q[head];
		cout<<now<<" "<<d[now]<<endl;
		head++;
		vis[now]=0;
		for(int i=0;i<edge[now].size();i++)
		{
			nod nex=edge[now][i];
			if(d[nex.to]==-1 || d[now]+nex.val<d[nex.to])
			{
				d[nex.to]=d[now]+nex.val;
				if(!vis[nex.to])
				{
					q[++tail]=nex.to;
					vis[nex.to]=1;
					// if(d[q[head]]>d[q[tail]])
					// 	swap(q[head],q[tail]);
				}
			}
		}
	}
	return d[e];
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int a,b,v;
		cin>>a>>b>>v;
		addedge(a,b,v);
	}
	int s,t;
	cin>>s>>t;
	cout<<spfa(s,t);
}

LCA

#include<iostream>
#include<stdio.h>
#include<vector>
using namespace std;
int n,m,pre[500005][23],dep[500005],root;
vector<int> edge[500005];
void dfs(int flag,int fa)
{
	for(int i=1;i<=22;i++)
		pre[flag][i]=pre[pre[flag][i-1]][i-1];
	for(int i=0;i<edge[flag].size();i++)
	{
		int nex=edge[flag][i];
		if(nex!=fa)
		{
			dep[nex]=dep[flag]+1;
			pre[nex][0]=flag;
			dfs(nex,flag);
		}
	}
}
int lca(int x,int y)
{
	if(dep[x]<dep[y])
		swap(x,y);
	for(int i=22;i>=0;i--)
		if(dep[x]-(1<<i)>=dep[y])
			x=pre[x][i];
	if(x==y)	return x;
	for(int i=22;i>=0;i--)
		if(pre[x][i]!=pre[y][i])
        {
            x=pre[x][i];
            y=pre[y][i];
        }
	return pre[x][0];
}
int main()
{
	int a,b;
	scanf("%d%d%d",&n,&m,&root);
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&a,&b);
		edge[a].push_back(b);
		edge[b].push_back(a);
	}
	dfs(root,-1);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&a,&b);
		printf("%d\n",lca(a,b));
	}
	return 0;
} n n n8uj 87n87777n 8

LCA(tarjian)

#include<iostream>
#include<vector>
using namespace std;
struct nod{
	int to,id;
};
int root,n,m,pre[500005],ans[500005],vis[500005];
vector<int> edge[500005];vector<nod> ques[500005];
int find(int x){return pre[x]==x?x:pre[x]=find(pre[x]);};
void join(int x,int y){x=find(x),y=find(y); if(x!=y) pre[x]=y;}
void addedge(int i,int j)
{
	edge[i].push_back(j);
	edge[j].push_back(i);
}
void addques(int i,int j,int id)
{
	ques[i].push_back((nod){j,id});
	ques[j].push_back((nod){i,id});
}
void dfs(int now)
{
	vis[now]=1;
	for(int i=0;i<ques[now].size();i++)
	{
		nod nex=ques[now][i];
		if(vis[nex.to])	ans[nex.id]=find(nex.to);
	}
	for(int i=0;i<edge[now].size();i++)
	{
		int nex=edge[now][i];
		if(!vis[nex])	dfs(nex),join(nex,now);
	}
}
int main()
{
	int x,y;
	cin>>n>>m>>root;
	for(int i=1;i<=n;i++) pre[i]=i;
	for(int i=1;i<=n-1;i++)
		cin>>x>>y,addedge(x,y);
	for(int i=1;i<=m;i++)
		cin>>x>>y,addques(x,y,i);
	dfs(root);
	for(int i=1;i<=m;i++)
		cout<<ans[i]<<endl;
}

并查集

int find(int x) {return pre[x]==x?x:pre[x]=find(pre[x]);}
void join(int x,int y) {x=find(x),y=find(y); if(x!=y) pre[x]=y;}

最小生成树

#include<iostream>
#include<algorithm>
using namespace std;
struct nod{
	int x,y,v;
}a[100005];
int ans,pre[100005];
bool cmp(nod i,nod j) {return i.v<j.v;}
int find(int x){return pre[x]==x?x:pre[x]=find(pre[x]);}
void join(int x,int y){x=find(x),y=find(y); if(x!=y) pre[x]=y;}
int main()
{
	int n,m,x,y,v;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		pre[i]=i;
	for(int i=1;i<=m;i++)
		cin>>a[i].x>>a[i].y>>a[i].v;
	sort(a+1,a+m+1,cmp);
	for(int i=1;i<=m;i++)
	{
		x=a[i].x,y=a[i].y;
		if(find(x)!=find(y))
			join(x,y),ans+=a[i].v;
	}
	cout<<ans;
	return 0;
}

dijkstra

#include<iostream>
#include<string.h>
#define INF 99999999
using namespace std;
bool vis[1005];
long long w[1005][1005],d[1005];
int n,m,k;
int main()
{	
	cin>>n>>m>>k;
	memset(vis,false,sizeof(vis));
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			w[i][j]=INF;
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		w[a][b]=c;
	}
	for(int i=1;i<=n;i++)
	{
		d[i]=INF;
	}
	d[k]=0;
	for(int i=1;i<=n;i++)
	{
		int x,Min=INF;
		for(int j=1;j<=n;j++)
			if(vis[j]==false && d[j]<=Min)
				Min=d[x=j];
		vis[x]=true;
		for(int j=1;j<=n;j++)
			d[j]=min(d[j],d[x]+w[x][j]);
	}
	d[k]=0;
	for(int i=1;i<=n;i++)
	{
		if(d[i]==INF)
			cout<<2147483647<<" ";
		else
			cout<<d[i]<<" ";
	}
	return 0;
}

floyd

#include<iostream>
#include<string.h>
#define INF 99999999
using namespace std;
int n,m,d[1005][1005];
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			d[i][j]=INF;
	for(int i=1;i<=m;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		d[a][b]=d[b][a]=c;
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)
			{
				if(i==j)	d[i][j]=0;
				else	d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
			}
	for(int i=1;i<=n;i++)
		cout<<d[1][i]<<' ';
}

kosaraju 强连通块

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<stack>
#define maxn 100005
using namespace std;
typedef long long LL;
int n,m;
vector<int> edge[maxn],redge[maxn];
vector<int> post;
bool vis[maxn];
int cmp[maxn];
void add_edge(int u,int v)
{
	edge[u].push_back(v);
	redge[v].push_back(u);
}
void dfs(int x)
{
	int lens=edge[x].size();
	vis[x]=1;
	for(int i=0;i<lens;i++)
	{
		int nex=edge[x][i];
		if(!vis[nex])
		dfs(nex);
	}
	post.push_back(x);
}
void dfs2(int x,int k)
{
	vis[x]=1;
	int lens=redge[x].size();
	cmp[x]=k;
	for(int i=0;i<lens;i++)
	{
		int nex=redge[x][i];
		if(!vis[nex])
		dfs2(nex,k);
	}
}
int kosaraju()
{
	for(int i=1;i<=n;i++)
	if(!vis[i])
	dfs(i);
	memset(vis,0,sizeof(vis));
	int k=0;
	int lens=post.size();
	for(int i=lens-1;i>=0;i--)
	if(!vis[post[i]])
	dfs2(post[i],k++);
	return k;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		add_edge(u,v);
	}
	cout<<kosaraju()<<endl;
	return 0;
}

二分图

#include<iostream>
#include<string.h>
using namespace std;
int n,m,k,link[5005];
bool a[5005][5005],vis[5005];
bool dfs(int x)
{
	for(int i=1;i<=m;i++)
		if(a[x][i] && !vis[i])
		{
			vis[i]=1;
			if(link[i]==-1 || dfs(link[i])) {link[i]=x; return 1;}
		}
	return 0;
}
int main()
{
	memset(link,-1,sizeof(link));
	int ans=0,x,y;
	cin>>n>>m>>k;
	for(int i=1;i<=k;i++)
	{
		cin>>x>>y;
		if(x<=n && y<=m)	a[x][y]=1;
	}
	for(int i=1;i<=n;i++)
	{
		memset(vis,0,sizeof(vis));
		if(dfs(i))	ans++;
	}
	cout<<ans;
	return 0;
}

最小瓶颈路

struct Edge{
    int u,v,w;
    Edge(int u=0,int v=0,int dist=0):u(u),v(v),w(dist){}
}e[maxm];
vector<Edge> vec[maxn];

bool cmp(const Edge& a,const Edge& b){
    return a.w<b.w;
}

int find(int x){
    return p[x]==x?x:p[x]=find(p[x]);
}

void kruskal()
{
    sort(e,e+m,cmp);
    for(int i=1;i<=n;i++)
        p[i]=i;
    int cnt=0;
    for(int i=0;i<m;i++){
        int x=find(e[i].u),y=find(e[i].v);
        if(x!=y){
            p[y]=x;
            vec[e[i].u].push_back(Edge(e[i].u, e[i].v, e[i].w));
            vec[e[i].v].push_back(Edge(e[i].v, e[i].u, e[i].w));
            if(++cnt==n-1)
                break;
        }
    }
}

void dfs(int index)
{
    vis[index]=1;
    for(int i=0;i<vec[index].size();i++)
    {
        int tmp=vec[index][i].v;
        if(!vis[tmp])
        {
            for(int j=1;j<=n;j++)
                if(vis[j])
                {
                    maxcost[j][tmp] = maxcost[tmp][j] = 
                        max(maxcost[j][index], vec[index][i].w);
                }
            pre[tmp]=index;
            dfs(tmp);
        }
    }
}

树剖

#include<iostream>
#include<vector>
using namespace std;
struct nod{
    int l,r;
    long long val,lazy;
}tree[800005];
vector<int> edge[200005];
int cnt=0,pre[200005],id[200005],lid[200005],siz[200005],top[200005],heavy[200005],dep[200005];
long long a[200005];
void pushdown(int now)
{
    tree[now*2].lazy+=tree[now].lazy;
    tree[now*2+1].lazy+=tree[now].lazy;
    tree[now*2].val+=tree[now].lazy*(tree[now*2].r-tree[now*2].l+1);
    tree[now*2+1].val+=tree[now].lazy*(tree[now*2+1].r-tree[now*2+1].l+1);
    tree[now].lazy=0;
}
void build(int l,int r,int now)
{
    tree[now].l=l,tree[now].r=r,tree[now].lazy=0;
    if(l==r)
    {
        tree[now].val=a[lid[l]];
        return;
    }
    int mid=(l+r)/2;
    build(l,mid,now*2);
    build(mid+1,r,now*2+1);
    tree[now].val=tree[now*2].val+tree[now*2+1].val;
}
long long ques(int l,int r,int now)
{
    if(l>tree[now].r || r<tree[now].l)	return 0;
    if(l<=tree[now].l && tree[now].r<=r)	return tree[now].val;
    pushdown(now);
    return ques(l,r,now*2)+ques(l,r,now*2+1);
}
void modify(int l,int r,int now,long long add)
{
    if(l>tree[now].r || r<tree[now].l)	return;
    if(l<=tree[now].l && tree[now].r<=r)
    {
        tree[now].lazy+=add;
        tree[now].val+=add*(tree[now].r-tree[now].l+1);
        return;
    }
    if(tree[now].lazy)	pushdown(now);
    int mid=(tree[now].l+tree[now].r)/2;
    if(l<=mid)	modify(l,r,now*2,add);
    if(r>mid)	modify(l,r,now*2+1,add);
    tree[now].val=tree[now*2].val+tree[now*2+1].val;
}
int dfs1(int now,int fa)
{
    long long ans=0,Max=0,x=0;
    for(int i=0;i<edge[now].size();i++)
    {
        int nex=edge[now][i];
        if(nex!=fa)
        {
            pre[nex]=now;
            dep[nex]=dep[now]+1;
            ans+=dfs1(nex,now);
            if(siz[nex]>Max)	Max=siz[x=nex];
        }
    }
    heavy[now]=x;
    siz[now]=ans+1;
    return ans+1;
}
void dfs2(int now,int Top,int fa)
{
    top[now]=Top;
    id[now]=++cnt;
    lid[cnt]=now;
    if(heavy[now]!=0)
        dfs2(heavy[now],Top,now);
    for(int i=0;i<edge[now].size();i++)
    {
        int nex=edge[now][i];
        if(nex!=fa)
            if(nex!=heavy[now])
                dfs2(nex,nex,now);
    }
}
void change(int x,int y,long long add)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]>dep[top[y]])	modify(id[top[x]],id[x],1,add),x=pre[top[x]];
        else	modify(id[top[y]],id[y],1,add),y=pre[top[y]];
    }
    if(dep[x]>dep[y])	swap(x,y);
    modify(id[x],id[y],1,add);
}
void changelow(int x,long long add)
{
    modify(id[x],id[x]+siz[x]-1,1,add);
}
long long query(int x,int y)
{
    long long ans=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]>dep[top[y]])	ans+=ques(id[top[x]],id[x],1),x=pre[top[x]];
        else	ans+=ques(id[top[y]],id[y],1),y=pre[top[y]];
    }
    if(dep[x]>dep[y])	swap(x,y);
    ans+=ques(id[x],id[y],1);
    return ans;
}
long long querylow(int x)
{
    return ques(id[x],id[x]+siz[x]-1,1);
}
int main()
{
    int n,q,root,d,x,y,z;
    long long p;
    cin>>n>>q>>root>>p;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    for(int i=1;i<n;i++)
        cin>>x>>y,edge[x].push_back(y),edge[y].push_back(x);
    dep[root]=1;
    dfs1(root,-1);
    dfs2(root,root,-1);
    build(1,n,1);
    while(q--)
    {
        cin>>d>>x;
        if(d==1) {cin>>y>>z; change(x,y,z); }
        else if(d==2) {cin>>y; cout<<query(x,y)%p<<endl; }
        else if(d==3) {cin>>z; changelow(x,z); }
        else	cout<<querylow(x)%p<<endl;
    }
    return 0;
}

>>字符串专题

KMP

#include<iostream>
#include<string.h>
using namespace std;
string a,b;
int n,m,next[1000005];
void findNext()
{
	next[0]=next[1]=0;
	for(int i=1;i<m;i++)
	{
		int j=next[i];
		while(j && b[j]!=b[i])	j=next[j];
		if(b[j]==b[i])	next[i+1]=j+1;
	}
}
void KMP()
{
	int j=0;
	for(int i=0;i<n;i++)
	{
		while(j && a[i]!=b[j])	j=next[j];
		if(a[i]==b[j])	j++;
		if(j==m) cout<<i-m+1<<endl;
	}
}
int main()
{
	cin>>a>>b;
	n=a.size(),m=b.size();
	findNext();
	KMP();
	for(int i=0;i<m;i++)
	    cout<<next[i]<<" ";
	return 0;
}

AC自动机

#include<iostream>
#include<queue>
using namespace std;
int cnt=0,fail[1000005],last[1000005];
struct nod
{
	char ch;
	int son[26],num,dep;
	nod() {for(int i=0;i<=25;i++) son[i]=0;dep=0;}
};
nod a[1000005];
void add(string str)
{
	int now=0;
	for(int j=0;j<str.size();j++)
	{
		int nex=str[j]-'a';
		if(a[now].son[nex])
			now=a[now].son[nex];
		else	a[now].son[nex]=++cnt,a[cnt].ch=str[j],a[cnt].dep=a[now].dep+1,now=cnt;
		if(j==str.size()-1)
			a[now].num++;
	}
}
void getFail()
{
	queue<int> q;
	for(int i=0;i<26;i++)
	{
		int nex=a[0].son[i];
		if(nex) q.push(nex);
	}
	while(!q.empty())
	{
		int now=q.front();q.pop();
		for(int i=0;i<26;i++)
		{
			int nex=a[now].son[i];
			if(!nex)	continue;
			q.push(nex);
			int x=fail[now];
			while(x && !a[x].son[i])	x=fail[x];
			fail[nex]=a[x].son[i];
			last[nex]=a[fail[nex]].num?fail[nex]:last[fail[nex]];
		}
	}
}
void find(string str)
{
	int n=str.size(),j=0;
	for(int i=0;i<n;i++)
	{
		int now=str[i]-'a';
		// cout<<now<<" "<<a[now].dep<<endl;
		while(j && !a[j].son[now])	j=fail[j];
		j=a[j].son[now];
		if(a[j].num)	cout<<i<<endl;
		int x=j;
		while(last[x] && a[last[x]].num)
			x=last[x],cout<<x<<endl;
	}
}
int main()
{
	int n,m;string str;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>str,add(str);
	getFail();
	for(int i=1;i<=cnt;i++)
		cout<<i<<" "<<a[i].ch<<" dep: "<<a[i].dep<<" fail: "<<fail[i]<<endl;
	cin>>m;
	for(int i=1;i<=m;i++)
		cin>>str,find(str);
}

Trie树

#include<iostream>
using namespace std;
struct nod
{
	char ch;
	int NEXT[26],num;
	nod() {for(int i=0;i<=25;i++) NEXT[i]=0;}
};
struct trietree
{
	int cnt;
	nod a[1000005];
	trietree() {cnt=1;}
	void add(string str)
	{
		int now=1;
		for(int j=0;j<str.size();j++)
		{
			int nex=str[j]-'a';
			if(a[now].NEXT[nex])
				now=a[now].NEXT[nex];
			else	a[now].NEXT[nex]=++cnt,now=cnt,a[cnt].ch=str[j];
			if(j==str.size()-1)
				a[now].num++;
		}
	}
	bool find(string str)
	{
		int now=1;
		for(int j=0;j<str.size();j++)
		{
			int nex=str[j]-'a';
			if(a[now].NEXT[nex])
				now=a[now].NEXT[nex];
			else return 0;
		}
		if(!a[now].num)	return 0;
		return 1;
	}
};
int main()
{
	trietree t;
	int n,m;
	string str;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>str;
		t.add(str);
	}
	for(int i=1;i<=m;i++)
	{
		cin>>str;
		if(t.find(str))	cout<<"YES\n";
		else	cout<<"NO\n";
	}
}

后缀数组

#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
struct nod{
	int a,b;
}tp[100005];
int n,rank[100005],sa[100005],height[100005],h[100005];
vector<int> arr[100005],ans[100005];
string a;
void Sa_sort()
{
	int sum=0;
	while((1<<sum)+1<=n)
	{
		int cnt=1;
		for(int i=1;i<=n-(1<<sum);i++)
			tp[i].a=rank[i],tp[i].b=rank[i+(1<<sum)];
		for(int i=n-(1<<sum)+1;i<=n;i++)
			tp[i].a=rank[i],tp[i].b=0;
		for(int i=1;i<=n;i++)
			arr[tp[i].b].push_back(i);
		for(int i=0;i<=n;i++)
			while(!arr[i].empty())
			{
				int now=arr[i][arr[i].size()-1];
				arr[i].pop_back();
				ans[tp[now].a].push_back(now);
			}
		for(int i=1;i<=n;i++)
		{
			for(int j=0;j<ans[i].size();j++)
			{
				int now=ans[i][j];
				rank[now]=cnt;
				if(j==ans[i].size()-1 || !(tp[now].a==tp[ans[i][j+1]].a && tp[now].b==tp[ans[i][j+1]].b))	cnt++;
			}
			ans[i].clear();
		}
		sum++;
	}
}
void getHeight()
{
	int sum=0;
	for(int i=1;i<=n;i++)
	{
		int j=sa[rank[i]-1];
		for(sum=max(sum-1,0);a[i+sum]==a[j+sum];sum++);
		height[rank[i]]=sum;
	}
}
int main()
{
	cin>>a;
	n=a.size();
	a=" "+a;
	for(int i=1;i<=n;i++)
		rank[i]=a[i]-'a'+1;
	Sa_sort();
	for(int i=1;i<=n;i++)
		sa[rank[i]]=i;
	getHeight();
	for(int i=1;i<=n;i++)
		cout<<height[i]<<" ";
	return 0;
}

字符串哈希

#include<iostream>
#include<map>
using namespace std;
map<pair<int,int>,int> Map;
int cci(char c)
{
	if('0'<=c && c<='9')	return c-'0';
	if('a'<=c && c<='z')	return c-'a'+10;
	if('A'<=c && c<='Z')	return c-'A'+36;
}
pair<int,int> hash(string s)
{
	int x=0,y=0;
	for(int i=0;i<s.size();i++)
		x=(x*62+cci(s[i]))%1000000007;
	for(int i=0;i<s.size();i++)
		y=(y*62+cci(s[i]))%1000000009;
	return make_pair(x,y);
}
int main()
{
	int n,ans=0;string s;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>s,Map[hash(s)]=1;
	for(map<pair<int,int>,int>::iterator it=Map.begin();it!=Map.end();++it)
		ans++;
	cout<<ans;
} 

>>数据结构专题

线段树(动态开点)

#include<iostream>
using namespace std;
long long n,m,cnt=1,sum[1000005],lazy[1000005],ls[1000005],rs[1000005];
void update(int i) {sum[i]=sum[ls[i]]+sum[rs[i]];}
void pushdown(int i,int l,int r)
{
	if(!lazy[i])	return;
	if(r-l<=0)	{lazy[i]=0; return;}
	int mid=(l+r)/2,v=lazy[i];
	if(!ls[i])	ls[i]=++cnt;
	if(!rs[i])	rs[i]=++cnt;
	sum[ls[i]]+=(mid-l+1)*v,sum[rs[i]]+=(r-mid)*v;
	lazy[ls[i]]+=v,lazy[rs[i]]+=v;
	lazy[i]=0;
}
void ins(int i,int l,int r,int L,int R,long long v)
{
	if(!i)	return;
	pushdown(i,l,r);
	if(L<=l && r<=R) {sum[i]+=(r-l+1)*v,lazy[i]=v; return;}
	int mid=(l+r)/2;
	if(!ls[i])	ls[i]=++cnt; if(!rs[i])	rs[i]=++cnt;
	if(L<=mid)	ins(ls[i],l,mid,L,R,v);
	if(mid+1<=R)	ins(rs[i],mid+1,r,L,R,v);
	update(i);
}
long long ques(int i,int l,int r,int L,int R)
{
	if(!i)	return 0;
	pushdown(i,l,r);
	if(L<=l && r<=R) {return sum[i];}
	int mid=(l+r)/2;
	long long ans=0;
	if(L<=mid)	ans+=ques(ls[i],l,mid,L,R);
	if(mid+1<=R)	ans+=ques(rs[i],mid+1,r,L,R);
	return ans;
}
int main()
{
	long long x,v,a,b;
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a,ins(1,1,n,i,i,a);
	for(int i=1;i<=m;i++)
	{
		cin>>x>>a>>b;
		if(x==1)	cin>>v,ins(1,1,n,a,b,v);
		else	cout<<ques(1,1,n,a,b)<<endl;
	}
	return 0;
}

主席树

#include<iostream>
#define LIM 1000000000
using namespace std;
int n,m,cnt,root[20000005],ls[20000005],rs[20000005],sum[20000005];
void ins(int i,int pre,long long l,long long r,long long x)
{
	sum[i]=sum[pre]+1;
	if(l==r) return;
	long long mid=(l+r)/2;
	if(x<=mid)
	{
		if(!ls[i])	ls[i]=++cnt;
		rs[i]=rs[pre];
		ins(ls[i],ls[pre],l,mid,x);
	}
	else
	{
		if(!rs[i])	rs[i]=++cnt;
		ls[i]=ls[pre];
		ins(rs[i],rs[pre],mid+1,r,x);
	}
}
long long ques(int i,int pre,long long l,long long r,long long x)
{
	if(l==r) return l;
	long long mid=(l+r)/2,lsum=sum[ls[i]]-sum[ls[pre]];
	if(x<=lsum)	return ques(ls[i],ls[pre],l,mid,x);
	else	return ques(rs[i],rs[pre],mid+1,r,x-lsum);
}
int main()
{
	long long x,y,k;
	cin>>n>>m;cnt=n;
	for(int i=1;i<=n;i++)	root[i]=i;
	for(int i=1;i<=n;i++)	cin>>x,ins(root[i],root[i-1],1,LIM*2,x+LIM);
	for(int i=1;i<=m;i++)
	{
		cin>>x>>y>>k;
		if(x>y)	swap(x,y);
		cout<<ques(root[y],root[x-1],1,LIM*2,k)-LIM<<endl;
	}
	return 0;
}

treap

#include<bits/stdc++.h>
using namespace std;
struct nod
{
	nod *l,*r;
	int val,pri,siz;
	nod(){val=siz=0,pri=rand();}
	void update(){siz=l->siz+r->siz+1;}
}*null=new nod();
nod *newnod(int x){nod *a=new nod(); a->val=x; a->l=a->r=null; a->siz=1; return a;}
struct treap{
	nod* root;
	treap(){root=null;}
	typedef pair<nod*,nod*> PAIR;
	nod *merge(nod *a,nod *b)
	{
		if(a==null || b==null)	return a==null?b:a;
		if((a->pri)<(b->pri)) {a->r=merge(a->r,b),a->update(); return a;}
		else {b->l=merge(a,b->l),b->update(); return b;}
	}
	PAIR split(nod *a,int k)
	{
		if(a==null)	return PAIR(null,null);
		PAIR b;
		if(a->l->siz>=k) b=split(a->l,k),a->l=b.second,b.second=a;
		else	b=split(a->r,k-(a->l)->siz-1),a->r=b.first,b.first=a;
		return b;
	}
	int getrank(nod *x,int k)
	{
		if(x==null)	return 0;
		return x->val>=k?getrank(x->l,k):getrank(x->r,k)+1+x->l->siz;
	}
	nod *kth(int k)
	{
		if(k<=0 || k>root->siz)	return null;
		PAIR a=split(root,k-1),b=split(a.second,1);
		nod *ans=b.first;
		root=merge(a.first,merge(b.first,b.second));
		return ans==null?null:ans;
	}
	void ins(int a)
	{
		PAIR x=split(root,getrank(root,a));
		root=merge(x.first,merge(newnod(a),x.second));
	}
	void del(int a)
	{
		PAIR x=split(root,getrank(root,a)),y=split(x.second,1);
		root=merge(x.first,y.second);
	}
	nod *last(nod *x,int a)
	{
		int Max=-2147483647;
		nod *ans;
		while(x!=null)
		{
			if(a>=(x->val))
			{
				if((x->val)>Max)	Max=(ans=x)->val;
				x=x->r;
			}
			else	x=x->l;
		}
		return ans;
	}
	nod *nex(nod *x,int a)
	{
		int Min=2147483647;
		nod *ans;
		while(x!=null)
		{
			if(a<(x->val))
			{
				if((x->val)<Min)	Min=(ans=x)->val;
				x=x->l;
			}
			else	x=x->r;
		}
		return ans;
	}
	void out(nod *x)
	{
		if(x==null)	return;
		cout<<x->val<<" ";
		out(x->l),out(x->r);
	}
};
int main()
{
	srand(time(0));
	treap Treap;
	int n,x;string str;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>x,Treap.ins(x);
	while(cin>>str)
	{
		if(str=="out")	{Treap.out(Treap.root),cout<<endl; continue;}
		cin>>x;
		if(str=="ins")	Treap.ins(x),Treap.out(Treap.root),cout<<endl;
		else if(str=="del")	Treap.del(x),Treap.out(Treap.root),cout<<endl;
		else if(str=="kth")	cout<<Treap.kth(x)->val<<endl;
		else if(str=="nex")	cout<<Treap.nex(Treap.root,x)->val<<endl;
		else if(str=="last")	cout<<Treap.last(Treap.root,x)->val<<endl;
	}
	return 0;
}

splay

#include<iostream>
#include<queue>
using namespace std;
struct nod{
	int sum,num,pre,val,siz,son[2];
	nod(){sum=num=pre=val=siz=son[0]=son[1]=0;}
}a[100005];
int root,cnt=0;
bool vis[100005];
queue<int> q;
void out()
{
	cout<<"---------------------------------------\n";
	for(int i=1;i<=cnt;i++)
		if(vis[i])
			cout<<a[i].sum<<"("<<a[i].num<<") siz "<<a[i].siz<<" val "<<a[i].val<<" : "<<a[a[i].son[0]].sum<<" "<<a[a[i].son[1]].sum<<" -> "<<a[i].pre<<endl;
	cout<<"root : "<<root<<" ("<<a[root].sum<<")"<<endl;
	cout<<"---------------------------------------\n";
}
void update(int now)
{
	if(now){a[now].val=a[a[now].son[0]].val+a[a[now].son[1]].val+a[now].sum*a[now].num;
	a[now].siz=a[a[now].son[0]].siz+a[a[now].son[1]].siz+a[now].num;}
}
void rotate(int now,int kind)
{
	if(now==0)	return;
	int fa=a[now].pre,anc=a[fa].pre;
	if(fa==root)	root=now;
	a[fa].son[kind^1]=a[now].son[kind],a[now].son[kind]=fa;
	a[fa].pre=now,a[a[fa].son[kind^1]].pre=fa;
	if(a[anc].son[0]==fa)	a[anc].son[0]=now;
	else	a[anc].son[1]=now;
	a[now].pre=anc;
	update(fa),update(now);
}
void splay(int now,int goal)
{
	if(now==0)	return;
	int fa=a[now].pre,anc=a[fa].pre;
	if(goal==root)	root=now;
	update(now);
	if(fa==0 || now==fa)	return;
	if(goal==now)	return;
	if(goal==fa)
	{
		if(a[fa].son[0]==now)	rotate(now,1);
		else	rotate(now,0);
		return;
	}
	if(a[anc].son[0]==fa)	{if(a[fa].son[0]==now)	rotate(fa,1),rotate(now,1);	else	rotate(now,0),rotate(now,1);}
	else	{if(a[fa].son[1]==now)	rotate(fa,0),rotate(now,0);	else	rotate(now,1),rotate(now,0);}
	if(goal==anc)	return;
	splay(now,goal);
}
void CLEAR(int now)
{
	nod k;
	a[now]=k;
	vis[now]=0;
}
void ins(int x,int now)
{
	if(a[now].sum==x)	{a[now].num++,splay(now,root); return;}
	int kind=(x>a[now].sum);
	if(!a[now].son[kind])
	{
		if(q.empty())
		{
			a[++cnt].num=a[cnt].val=1,a[cnt].sum=x,a[now].son[kind]=cnt,a[cnt].pre=now,a[cnt].siz=1;
			vis[cnt]=1;
			splay(cnt,root);
		}
		else
		{
			int nex=q.front();q.pop();
			a[nex].num=a[nex].val=1,a[nex].sum=x,a[now].son[kind]=nex,a[nex].pre=now,a[nex].siz=1;
			vis[nex]=1;
			splay(nex,root);
		}
		return;
	}
	ins(x,a[now].son[kind]);
}
void del(int x,int now)
{
	if(now==0)	return;
	if(a[now].sum==x)
	{
		if(a[now].num>1)	a[now].num--,splay(now,root);
		else
		{
			int fa=a[now].pre,lson=a[now].son[0],rson=a[now].son[1],kind=(a[fa].son[0]==now)?0:1;
			if(!lson && !rson)
			{
				a[fa].son[kind]=0;
				if(root==now)	root=0;
				update(fa),splay(fa,root);
				CLEAR(now);
				q.push(now);
			}
			else if(!(lson && rson))
			{
				if(root==now) {if(rson)	root=rson; else	root=lson;}
				if(rson)	a[fa].son[kind]=rson,a[rson].pre=fa,splay(rson,root);
				else	a[fa].son[kind]=lson,a[lson].pre=fa,splay(lson,root);
				CLEAR(now);
				q.push(now);
			}
			else
			{
				if(a[lson].siz>a[rson].siz)	rotate(lson,1);
				else	rotate(rson,0);
				del(x,now);
			}
			return;
		}
	}
	int kind=(x>a[now].sum);
	del(x,a[now].son[kind]);
}
pair<int,int> find(int x,int now)
{
	if(x==a[now].sum)	return make_pair(now,0);
	int kind=(x>a[now].sum);
	if(a[now].son[kind])	return find(x,a[now].son[kind]);
	if(x<a[now].sum)	return make_pair(now,1);
	return make_pair(now,2);
}
int findl(int now) {return a[now].son[0]?findl(a[now].son[0]):now;}
int findr(int now) {return a[now].son[1]?findr(a[now].son[1]):now;}
int getclose(int x,int kind)
{
	pair<int,int> now=find(x,root);
	splay(now.first,root);
	if(kind) {if(!now.second || now.second==2) {if(a[now.first].son[1]) return findl(a[now.first].son[1]); return 0;}}
	else	 {if(!now.second || now.second==1) {if(a[now.first].son[0]) return findr(a[now.first].son[0]); return 0;}}
	return now.first;
}
void clean(int now)
{
	if(a[now].son[0])	clean(a[now].son[0]);
	if(a[now].son[1])	clean(a[now].son[1]);
	CLEAR(now);
	q.push(now);
}
void cut(int l,int r)
{
	int last=getclose(l,0),nex=getclose(r,1);
	if(last && nex)
	{
		splay(last,root);
		splay(nex,a[root].son[1]);
		clean(a[nex].son[0]),a[nex].son[0]=0;
	}
	else if(last)
	{
		splay(last,root);
		clean(a[root].son[1]),a[root].son[1]=0;
	}
	else if(nex)
	{
		splay(nex,root);
		clean(a[root].son[0]),a[root].son[0]=0;
	}
	else	clean(root),root=0;
}
int main()
{
	int n,m,x,y;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>x,ins(x,root);
	out();
	string str;
	while(cin>>str)
	{
		if(str=="rot")	cin>>x>>y,rotate(x,y);
		else if(str=="splay")	cin>>x>>y,splay(x,y);
		else if(str=="ins")	cin>>x,ins(x,root);
		else if(str=="del")	cin>>x,del(x,root);
		else if(str=="nex")	cin>>x,cout<<a[getclose(x,1)].sum<<endl;
		else if(str=="pre")	cin>>x,cout<<a[getclose(x,0)].sum<<endl;
		else if(str=="cut")	cin>>x>>y,cut(x,y);
		else if(str=="add")
		{
			cin>>n;
			for(int i=1;i<=n;i++)
				cin>>x,ins(x,root);
		}
		out();
	}
	return 0;
}

ST表

#include<stdio.h>
#include<iostream>
using namespace std;
int n,m,sum[200005][25],log2[200005];
int main()
{
	for(int i=2;i<=200000;i++)
		log2[i]=log2[i/2]+1;
	int x,y;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		scanf("%d",&sum[i][0]);
	for(int i=1;i<=log2[n];i++)
		for(int j=1;j+(1<<i)<=n;j++)
			sum[j][i]=max(sum[j][i-1],sum[j+(1<<(i-1))][i-1]);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&x,&y);
		int t=log2[y-x+1];
		printf("%d\n",max(sum[x][t],sum[y-(1<<t)+1][t]));
	}
	return 0;
}

树状数组

#include<iostream>
using namespace std;
int n,m,sum[200005];
int lowbit(int x) {return x&(-x);}
void ins(int x,int v)
{
	for(int i=x;i<=n;i+=lowbit(i))
		sum[i]+=v;
}
int ques(int x)
{
	int ans=0;
	for(int i=x;i>0;i-=lowbit(i))
		ans+=sum[i];
	return ans;
}
int main()
{
	int x,l,r;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		cin>>x,ins(i,x);
	for(int i=1;i<=m;i++)
		cin>>l>>r,cout<<ques(r)-ques(l-1)<<endl;
	return 0;
}


>> 其他

三分法

#include<iostream>
#include<stdio.h>
using namespace std;
int n;double a[15];
double cal(double x)
{
	double sum=0;
	for(int i=1;i<=n+1;i++)
		sum=sum*x+a[i];
	return sum; 
}
int main()
{
	double l,r;
	cin>>n>>l>>r;
	for(int i=1;i<=n+1;i++)
		cin>>a[i];
	while(l+0.000001<r)
	{
		double mid=(l+r)/2,mid2=(mid+r)/2;
		if(cal(mid)<cal(mid2))	l=mid;
		else	r=mid2;
	}
	printf("%.5f",l);
}

归并排序

#include<iostream>
using namespace std;
struct nod
{
	char ch;
	int NEXT[26],num;
	nod() {for(int i=0;i<=25;i++) NEXT[i]=0;}
};
struct trietree
{
	int cnt;
	nod a[1000005];
	trietree() {cnt=1;}
	void add(string str)
	{
		int now=1;
		for(int j=0;j<str.size();j++)
		{
			int nex=str[j]-'a';
			if(a[now].NEXT[nex])
				now=a[now].NEXT[nex];
			else	a[now].NEXT[nex]=++cnt,now=cnt,a[cnt].ch=str[j];
			if(j==str.size()-1)
				a[now].num++;
		}
	}
	bool find(string str)
	{
		int now=1;
		for(int j=0;j<str.size();j++)
		{
			int nex=str[j]-'a';
			if(a[now].NEXT[nex])
				now=a[now].NEXT[nex];
			else return 0;
		}
		if(!a[now].num)	return 0;
		return 1;
	}
};
int main()
{
	trietree t;
	int n,m;
	string str;
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		cin>>str;
		t.add(str);
	}
	for(int i=1;i<=m;i++)
	{
		cin>>str;
		if(t.find(str))	cout<<"YES\n";
		else	cout<<"NO\n";
	}
}

拓扑排序

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
vector<int> a[100005];
queue<int> q,s;
int n,deg[100005];
void topo()
{
	for(int i=1;i<=n;i++)
		if(deg[i]==0)
			q.push(i);
	while(!q.empty())
	{
		int now=q.front();q.pop();
		s.push(now);
		for(int i=0;i<a[now].size();i++)
		{
			int nex=a[now][i];
			deg[nex]--;
			if(!deg[nex])	q.push(nex);
		}
	}
}
int main()
{
	int x,y,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++)
		cin>>x>>y,a[x].push_back(y),deg[y]++;
	topo();
	while(!s.empty())cout<<s.front()<<" ",s.pop();
}

线段覆盖

#include<iostream>
#include<algorithm>
#define INF 2147483647
using namespace std;
struct nod{
	int l,r;
}a[2000005];
int n,ans,now=-INF;
bool cmp(nod i,nod j){return i.r==j.r?i.l<j.l:i.r<j.r;}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i].l>>a[i].r;
	sort(a+1,a+n+1,cmp);
	for(int i=1;i<=n;i++)
		if(a[i].l>=now)	now=a[i].r,ans++;
	cout<<ans;
	return 0;
}

最长上升子序列

#include<iostream>
#define INF 99999999
using namespace std;
int n,ans=-1,a[5005],dp[5005];
int main()
{
	a[0]=-INF;
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=1;i<=n;i++)
		for(int j=0;j<i;j++)
			if(a[j]<=a[i])
				dp[i]=max(dp[i],dp[j]+1);
	for(int i=1;i<=n;i++)
		ans=max(ans,dp[i]);
	cout<<ans;
	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值