写在前面:
这里会挂一些自己认为很重要的模板,没理解的就没有注释了,等理解了就更
排序算法模板:
快速排序(简单分治思想,时间复杂度从(O_(nlog{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_(nlog{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_(mlog{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_(mlog{m}+malpha(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_(mlog{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_(mlog{m}+malpha(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;
}
图论算法结束
(nlog{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
",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;
}