模板总结(不定期更新)

写在前面:

这里会挂一些自己认为很重要的模板,没理解的就没有注释了,等理解了就更

排序算法模板:

快速排序(简单分治思想,时间复杂度从\(O_(n\log{n})\)\(O_(n^2)\)不等,及其不稳定)
\(code:\)

#include<iostream>
using namespace std;
long long a[100001],n;
void qs(int l,int r){
    int bz=a[(l+r)/2],i=l,j=r;
    while(i<=j){
        while(a[i]<bz)++i;
        while(a[j]>bz)--j;
        if(i<=j)
            swap(a[i],a[j]),++i,--j;
    }
    if(l<j)qs(l,j);
    if(r>i)qs(i,r);
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    qs(1,n);
    for(int i=1;i<=n-1;i++)
        cout<<a[i]<<' ';
    cout<<a[n]<<endl;
    return 0;
}

题目链接

归并排序(分治思想,时间复杂度稳定在\(O_(n\log{n})\))
\(Code:\)

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=5e5+1;
inline int read(){
    char ch=getchar();
    int r=0,s=1;
    while(ch>57||ch<48)s=ch==45?0:s,ch=getchar();
    while(ch>=48&&ch<=57)r=(r<<1)+(r<<3)+(ch^48),ch=getchar();
    return s?r:-r;
}
int n;
int a[maxn],tmp[maxn];
void ms(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1,i=l,j=mid+1,cnt=l;
    ms(l,mid);
    ms(mid+1,r);
    while(i<=mid&&j<=r){
        if(a[j]>=a[i])tmp[cnt]=a[i],i++,cnt++;
        if(a[i]>a[j])tmp[cnt]=a[j],j++,cnt++;
    }
    while(i<=mid)tmp[cnt]=a[i],i++,cnt++;
    while(j<=r)tmp[cnt]=a[j],j++,cnt++;
    for(i=l;i<=r;++i)a[i]=tmp[i];
    return;
}
    
int main(){
    n=read();
    for(int i=1;i<=n;++i)a[i]=read();
    ms(1,n);
    for(int i=1;i<=n;++i)printf("%d ",a[i]);
    return 0;
}

排序算法结束

图论算法模板

单源最短路径:

\(SPFA\)(死了的那个,时间复杂度\(O_(km)\)\(O_(nm)\),不被卡就会跑得飞快)

\(Code:\)

const int maxn=1e5+5,maxm=5e5+5;
queue< int > q;
struct edge{int to,nxt,w;}e[maxm<<1]
int head[maxn],dis[maxn],v[maxn];
void SPFA(int s){
    int x,y,z;
    memset(dis,0x3f,sizeof(dis));
    memset(v,0,sizeof(v));
    dis[s]=0,v[s]=1,q.push(s);
    while(!q.empty()){
        x=q.front(),v[x]=0,q.pop();
        for(int i=head[x];i;i=e[i].nxt){
            y=e[i].to,z=e[i].w;
            if(dis[y]>dis[x]+z){
                dis[y]=dis[x]+z;
                if(!v[y])v[y]=1,q.push(y);
            }
        }
    }
    return;
}

\(Dijkstra\)(没有\(SPFA\)的时候要坚强,多写写堆优化,时间复杂度\(O_((n+m)\log{n})\))

\(Code:\)

const int maxn=1e5+5,maxm=5e5+5;
priority_queue< pair< int , int > > q;
struct edge{int to,nxt,w;}e[maxm<<1]
int head[maxn],dis[maxn],vis[maxn];
void Dijkstra(int s){
    int x,y,z;
    memset(dis,0x3f,sizeof(dis));
    memset(v,0,sizeof(vis));
    dis[s]=0,q.push(make_pair(0,s));
    while(!q.empty()){
        x=q.top().second,q.pop();
        if(vis[x])continue;
        vis[x]=1;
        for(int i=head[x];i;i=e[i].nxt){
            y=e[i].to,z=e[i].w;
            if(dis[y]>dis[x]+z){
                dis[y]=dis[x]+z;
                if(!vis[y])q.push(make_pair(-dis[y],y));
            }
        }
    }
    return;
}

\(Prim + Priority Queue\)(时间复杂度为\(O_(m\log{n})\),稠密图上表现较优)

\(Code:\)

const int maxn=5005,maxm=2e5+5;
priority_queue< pair< int , int > > q;
struct edge{int to,nxt,w;}e[maxm<<1];
int n,m,cnt,ans,tot;
int head[maxn],dis[maxn],vis[maxn];

void Prim(){
	int x,y,z;
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[1]=0,q.push(make_pair(0,1));
	while(q.size()){
		x=q.top().second,q.pop();
		if(vis[x])continue;
		vis[x]=1,ans+=dis[x],++tot;
		for(re int i=head[x];i;i=e[i].nxt){
			y=e[i].to,z=e[i].w;
			if(dis[y]>z){
				dis[y]=z;
				if(!vis[y])q.push(make_pair(-dis[y],y));
			}
		}
	}
	return;
}

\(Kruskal\)(时间复杂度为\(O_(m\log{m}+m\alpha(n))\))

\(Code:\)

#define re register
const int maxn=5005,maxm=2e5+5;
struct edge{int u,v,w;}e[maxm];
int n,m,pd=1;
int f[maxn];

bool cmp(edge x,edge y){return x.w<y.w;}

inline int fin(int x){return f[x]==x?x:f[x]=fin(f[x]);}

void Kruskal(){
    int f1,f2,k;
    sort(e+1,e+m+1,cmp);
    for(re int i=1;i<=n;++i)f[i]=i;
    for(re int i=1;i<=m;++i){
        f1=fin(e[i].u),f2=fin(e[i].v);
        if(f1==f2)continue;
        f[f1]=f2;
        ans+=e[i].w;
        if(++k==n-1)break;
    }
    if(k<n-1)pd=0;
    return;
}

\(Prim + PriorityQueue\)(时间复杂度为\(O_(m\log{n})\),稠密图上表现较优)

\(Code:\)

const int maxn=5005,maxm=2e5+5;
priority_queue< pair< int , int > > q;
struct edge{int to,nxt,w;}e[maxm<<1];
int n,m,cnt,ans,tot;
int head[maxn],dis[maxn],vis[maxn];

void Prim(){
	int x,y,z;
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[1]=0,q.push(make_pair(0,1));
	while(q.size()){
		x=q.top().second,q.pop();
		if(vis[x])continue;
		vis[x]=1,ans+=dis[x],++tot;
		for(re int i=head[x];i;i=e[i].nxt){
			y=e[i].to,z=e[i].w;
			if(dis[y]>z){
				dis[y]=z;
				if(!vis[y])q.push(make_pair(-dis[y],y));
			}
		}
	}
	return;
}

\(Kruskal\)(时间复杂度为\(O_(m\log{m}+m\alpha(n))\))

\(Code:\)

#define re register
const int maxn=5005,maxm=2e5+5;
struct edge{int u,v,w;}e[maxm];
int n,m,pd=1;
int f[maxn];

bool cmp(edge x,edge y){return x.w<y.w;}

inline int fin(int x){return f[x]==x?x:f[x]=fin(f[x]);}

void Kruskal(){
    int f1,f2,k;
    sort(e+1,e+m+1,cmp);
    for(re int i=1;i<=n;++i)f[i]=i;
    for(re int i=1;i<=m;++i){
        f1=fin(e[i].u),f2=fin(e[i].v);
        if(f1==f2)continue;
        f[f1]=f2;
        ans+=e[i].w;
        if(++k==n-1)break;
    }
    if(k<n-1)pd=0;
    return;
}

图论算法结束

\(n\log{n}\)数据结构:

树状数组(可用于求前缀和)

\(Code:\)

#define lowbit(x) (x&-x)
const int maxn=5e5+5;

int n;
int a[maxn],c[maxn];

void update(int x,int y){//更新
    while(x<=n){
        c[x]+=y;
        x+=lowbit(x);
    }
    return;
}

int sum(int x){//查询前缀和
    int ans=0;
    while(x>0){
        ans+=c[x];
        x-=lowbit(x);
    }
    return ans;
}

线段树:

\(Code:\)

#include<bits/stdc++.h>
#define ll long long
#define lc(x) (x<<1)
#define rc(x) (x<<1|1)
#define midd ((l+r)>>1)
using namespace std;
const int maxn=1e5+5;
inline int read(){
    char ch=getchar();
    int r=0,s=1;
    while(ch>57||ch<48)s=ch==45?0:s,ch=getchar();
    while(ch>=48&&ch<=57)r=r*10+ch-48,ch=getchar();
    return s?r:-r;
}

ll sum[maxn<<2],tagm[maxn<<2],taga[maxn<<2],a[maxn];
int n,m;
ll HA;

void push_up(int p){
    sum[p]=(sum[lc(p)]%HA+sum[rc(p)]%HA)%HA;
    return;
}

void build(int p,int l,int r){
    tagm[p]=1,taga[p]=0;
    if(l==r){sum[p]=a[l];return;}
    int mid=midd;
    build(lc(p),l,mid);build(rc(p),mid+1,r);
    push_up(p);
    return;
}

void push_down(int p,int l,int r){
    int mid=midd;
    sum[lc(p)]=((sum[lc(p)]*tagm[p])+(taga[p]*(mid-l+1)))%HA;
    sum[rc(p)]=((sum[rc(p)]*tagm[p])+(taga[p]*(r-mid)))%HA;
    taga[lc(p)]=(tagm[p]*taga[lc(p)]+taga[p])%HA,tagm[lc(p)]=(tagm[lc(p)]*tagm[p])%HA;
    taga[rc(p)]=(tagm[p]*taga[rc(p)]+taga[p])%HA,tagm[rc(p)]=(tagm[rc(p)]*tagm[p])%HA;
    taga[p]=0,tagm[p]=1;
    return;
}

void update_mul(int p,int l,int r,int cl,int cr,int k){
    if(cl>r||cr<l)return;
    if(cl<=l&&r<=cr){sum[p]=(sum[p]*k)%HA,tagm[p]=(tagm[p]*k)%HA,taga[p]=(taga[p]*k)%HA;return;}
    push_down(p,l,r);
    int mid=midd;
    if(mid>=cl) update_mul(lc(p),l,mid,cl,cr,k);
    if(cr>mid) update_mul(rc(p),mid+1,r,cl,cr,k);
    push_up(p);
    return;
}

void update_add(int p,int l,int r,int cl,int cr,int k){
    if(cl>r||cr<l)return;
    if(cl<=l&&r<=cr){sum[p]=(sum[p]%HA+((r-l+1)*k)%HA)%HA,taga[p]=(taga[p]+k)%HA;return;}
    push_down(p,l,r);
    int mid=midd;
    if(cl<=mid)update_add(lc(p),l,mid,cl,cr,k);
    if(cr>mid)update_add(rc(p),mid+1,r,cl,cr,k);
    push_up(p);
    return;
}

ll ask(int p,int l,int r,int al,int ar){
    if(al>r||ar<l)return 0;
    if(al<=l&&r<=ar)return sum[p];
    push_down(p,l,r);
    ll ans=0;
    int mid=midd;
    if(al<=mid) ans=(ans+ask(lc(p),l,mid,al,ar))%HA;
    if(ar>mid) ans=(ans+ask(rc(p),mid+1,r,al,ar))%HA;
    return ans;
}

int main(){
    n=read(),m=read();
    scanf("%lld",&HA);
    for(int i=1;i<=n;++i)a[i]=read();
    build(1,1,n);
    int k,x,y,z;
    while(m--){
        k=read();
        switch(k){
        case 1:x=read(),y=read(),z=read(),update_mul(1,1,n,x,y,z);break;
        case 2:x=read(),y=read(),z=read(),update_add(1,1,n,x,y,z);break;
        case 3:x=read(),y=read(),printf("%lld\n",ask(1,1,n,x,y));break;
        default:break;
        }
    }
    return 0;
}

乱入一个分块2333

#define ll long long
#define re register
void build(){
    re int s=sqrt(n);
    re int num=n/s;
    if(n%s)++num;
    for(re int i=1;i<=n;++i)pos[i]=(i-1)/s+1,sum[(i-1)/s+1]+=a[i];
    for(re int i=1;i<=num;++i)l[i]=(i-1)*s+1,r[i]=i*s;
    r[num]=n;
    return;
}

void update(int le,int ri,int d){
    re int x=pos[le],y=pos[ri];
    if(x==y){for(re int i=le;i<=ri;++i)a[i]+=d,sum[x]+=d;return;}
    for(re int i=le;i<=r[x];++i)a[i]+=d,sum[x]+=d;
    for(re int i=l[y];i<=ri;++i)a[i]+=d,sum[y]+=d;
    for(re int i=x+1;i<=y-1;++i)tag[i]+=d,sum[i]+=d*(r[i]-l[i]+1);
    return;
}

ll query(int le,int ri){
    re int x=pos[le],y=pos[ri];
    re ll ans=0;
    if(tag[x]){for(re int i=l[x];i<=r[x];++i)a[i]+=tag[x];tag[x]=0;}
    if(tag[y]){for(re int i=l[y];i<=r[y];++i)a[i]+=tag[y];tag[y]=0;}
    if(x==y){for(re int i=le;i<=ri;++i)ans+=a[i];return ans;}
    for(re int i=le;i<=r[x];++i)ans+=a[i];
    for(re int i=l[y];i<=ri;++i)ans+=a[i];
    for(re int i=x+1;i<=y-1;++i)ans+=sum[i];
    return ans;
}
posted @ 2018-11-06 13:03  绥棱泷Narcissus  阅读(172)  评论(0编辑  收藏  举报