模板大全
一·算法部分
(一)排序部分
1.冒泡排序
#include<iostream>
#include<cstdio>
using namespace std;
int n;
int a[3000];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n-1;i++)
for(int j=2;j<=n;j++)
if(a[j-1]>a[j])swap(a[j-1],a[j]);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
}
2.选择排序
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[100001];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=2;i<=n;i++)
{
for(int j=i;j>1;j--)
{
if(a[j]<a[j-1])
{
int temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
}
else break;
}
}
for(int i=1;i<=n;i++)printf("%d ",a[i]);
}
3.插入排序
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[100001];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=2;i<=n;i++)
{
int l=0,r=i-1;
int g=a[i];
while(l<=r)
{
int mid=(l+r)/2;
if(a[mid]>g)r=mid-1;
else l=mid+1;
}
for(int j=i-1;j>=l;j--)a[j+1]=a[j];
a[l]=g;
}
for(int i=1;i<=n;i++)printf("%d ",a[i]);
}
4.归并排序
#include<iostream>
#include<cstdio>
using namespace std;
int n,a[100001];
void up(int l,int mid,int r)
{
int i=l,num[100001],tot=0,j=mid+1;
while(i<=mid&&j<=r)
{
if(a[i]>a[j])num[++tot]=a[j++];
else num[++tot]=a[i++];
}
while(i<=mid)num[++tot]=a[i++];
while(j<=r)num[++tot]=a[j++];
for(int i=1;i<=tot;i++)
{
a[l++]=num[i];
}
}
void sep(int l,int r)
{
if(l==r)return ;
int mid=l+(r-l)/2;
sep(l,mid);
sep(mid+1,r);
up(l,mid,r);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
sep(1,n);
for(int i=1;i<=n;i++)printf("%d ",a[i]);
}
5.快速排序(sort)
(二)快速幂
#include<bits/stdc++.h>
using namespace std;
long long b,p,k;
long long ans,bas;
int main()
{
ans=1;
cin>>b>>p>>k;
int t=p;
bas=b;
while(p!=0)
{
if(p & 1 ==1)ans=((ans%k)*(bas%k))%k;
bas=((bas%k)*(bas%k))%k;
p >>= 1;
}
cout<<b<<"^"<<t<<" mod "<<k<<"="<<ans%k;
}
(三)三分
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int n;
double l,r;
double a[14];
double calc(double a,double b)
{
double sum=1;
for(int i=1;i<=b;i++)sum*=a;
return sum;
}
int main()
{
scanf("%d%lf%lf",&n,&l,&r);
for(int i=n;i>=0;i--)scanf("%lf",&a[i]);
while(l+0.000001<=r)
{
double lmid=(l+r)/2;
double rmid=(lmid+r)/2;
double sum1=0,sum2=0;
for(int i=n;i>=1;i--)sum1+=a[i]*calc(lmid,i),sum2+=a[i]*calc(rmid,i);
sum1+=a[0];sum2+=a[0];
// printf("\nf(%lf)=%lf f(%lf)=%lf \n",lmid,sum1,rmid,sum2);
sum1>sum2?r=rmid:l=lmid;
}
printf("%.5lf",l);
}
(四)ST表
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int a[100010];
int f[100010][60];
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
f[i][0]=a[i];
}
int LC=floor(log(n)/log(2.0));
for(int j=1;j<=LC;++j)
{
for(int i=1;i<=n-(1<<j)+1;++i)
{
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
}
for(int i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
int p=floor(log(r-l+1)/log(2));
printf("%d\n",max(f[l][p],f[r-(1<<p)+1][p]));
}
return 0;
}
(五)字符串相关
manacher算法
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char s[11100000];
char new_s[11100000<<1];
int f[11100000<<1];
int ans;
int Init()
{
new_s[0]='$';
int k=1;
int p=strlen(s);
for(int i=0;i<p;i++)
{
new_s[k++]=s[i];
new_s[k++]='#';
}
new_s[k]='\0';
return k;
}
int main()
{
scanf("%s",s);
int len=Init();
int id=0,mx=0;
for(int i=1;i<len;i++)
{
f[i]=mx>i?min(f[2*id-i],mx-i):1;
while(new_s[i+f[i]]==new_s[i-f[i]])f[i]++;
if(i+f[i]>mx)mx=i+f[i],id=i;
ans=max(ans,f[i]);
}
printf("%d",ans-1);
// for(int i=1;new_s[i]!='\0';i++)cout<<new_s[i]<<" ";cout<<endl;
// for(int i=1;new_s[i]!='\0';i++)cout<<f[i]<<" ";
}
kmp字符串匹配
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define N int(1e6+2)
#define M int(1e6+2)
int n,m,ans,nx[N];
char S[N],T[M];
void getnx()
{
nx[0]=nx[1]=0;
for(int i=2;i<=n;i++)
{
int p=nx[i-1];
while(p&&S[i]!=S[p+1])p=nx[p];
if(S[i]==S[p+1])nx[i]=p+1;
else nx[i]=0;
}
}
int main()
{
scanf("%s",T+1);
scanf("%s",S+1);
m=strlen(T+1),n=strlen(S+1);
getnx();
int p=0;
for(int i=1;i<=m;i++)
{
while(p&&T[i]!=S[p+1])p=nx[p];
if(T[i]==S[p+1])++p;
else p=0;
if(p==n)printf("%d\n",i-n+1),p=nx[p];
}
for(int i=1;i<=n;i++)printf("%d ",nx[i]);
return 0;
}
字符串hash
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ull unsigned long long
using namespace std;
const ull base=233;
ull pw[100005],hs[100005];
char S[100005];
int n;
void init()
{ pw[0]=1;
for(int i=1;i<=n;i++)pw[i]=pw[i-1]*base;
hs[0]=0;
for(int i=1;i<=n;i++)hs[i]=hs[i-1]*base+S[i];
}
inline ull geths(int l,int r)
{ return hs[r]-hs[l-1]*pw[r-l+1];
}
int main()
{ return 0;
}
(六)网络流
二分图匹配匈牙利
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int edge[1011][1011];
int cx[1001],cy[1001];
bool vis[1011];
int n,m,e,ans;
int path(int u)
{
for(int v=0;v<=m;v++)
{
if(edge[u][v]&&!vis[v])
{
vis[v]=1;
if(cy[v]==-1||path(cy[v]))
{
cx[u]=v;
cy[v]=u;
return 1;
}
}
}
return 0;
}
int main()
{
memset(cx,-1,sizeof(cx));
memset(cy,-1,sizeof(cy));
scanf("%d%d%d",&n,&m,&e);
int x,y;
for(int i=1;i<=e;++i)scanf("%d%d",&x,&y),edge[x][y]=1;
for(int i=1;i<=n;i++)
{
if(cx[i]==-1)
{
memset(vis,0,sizeof(vis));
ans+=path(i);
}
}
printf("%d",ans);
}
网络最大流
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=1e9;
int n,m,x,y,z,maxflow,deep[500];//deep深度
struct Edge{
int next,to,dis;
}edge[500];
int num_edge=-1,head[500],cur[500];//cur用于复制head
queue <int> q;
void add_edge(int from,int to,int dis,bool flag)
{
edge[++num_edge].next=head[from];
edge[num_edge].to=to;
if (flag) edge[num_edge].dis=dis;//反图的边权为 0
head[from]=num_edge;
}
//bfs用来分层
bool bfs(int s,int t)
{
memset(deep,0x7f,sizeof(deep));
while (!q.empty()) q.pop();
for (int i=1; i<=n; i++) cur[i]=head[i];
deep[s]=0;
q.push(s);
while (!q.empty())
{
int now=q.front(); q.pop();
for (int i=head[now]; i!=-1; i=edge[i].next)
{
if (deep[edge[i].to]>inf && edge[i].dis)//dis在此处用来做标记 是正图还是返图
{
deep[edge[i].to]=deep[now]+1;
q.push(edge[i].to);
}
}
}
if (deep[t]<inf) return true;
else return false;
}
//dfs找增加的流的量
int dfs(int now,int t,int limit)//limit为源点到这个点的路径上的最小边权
{
if (!limit || now==t) return limit;
int flow=0,f;
for (int i=cur[now]; i!=-1; i=edge[i].next)
{
cur[now]=i;
if (deep[edge[i].to]==deep[now]+1 && (f=dfs(edge[i].to,t,min(limit,edge[i].dis))))
{
flow+=f;
limit-=f;
edge[i].dis-=f;
edge[i^1].dis+=f;
if (!limit) break;
}
}
return flow;
}
void Dinic(int s,int t)
{
while (bfs(s,t))
maxflow+=dfs(s,t,inf);
}
int main()
{
// for (int i=0; i<=500; i++) edge[i].next=-1;
memset(head,-1,sizeof(head));
scanf("%d%d",&m,&n);
for (int i=1; i<=m; i++)
{
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z,1); add_edge(y,x,z,0);
}
Dinic(1,n);
printf("%d",maxflow);
return 0;
}
(七)树图相关
倍增LCA
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
const int maxn=5e5+4;
int n,m,s;
int head[maxn],tot;
int d[maxn],p[maxn][21];
struct ahah{
int nxt,to;
}edge[maxn<<1];
void add(int u,int v)
{
edge[++tot].nxt=head[u];edge[tot].to=v;head[u]=tot;
}
void dfs(int u,int fa)
{
d[u]=d[fa]+1;p[u][0]=fa;
for(int i=1;(1<<i)<=d[u];i++)
p[u][i]=p[p[u][i-1]][i-1];
for(int i=head[u];i;i=edge[i].nxt)
{
int v=edge[i].to;
if(v!=fa)dfs(v,u);
}
}
int lca(int a,int b)
{
if(d[a]>d[b])swap(a,b);
for(int i=20;i>=0;i--)
if(d[a]<=d[b]-(1<<i))b=p[b][i];
if(a==b)return a;
for(int i=20;i>=0;i--)
{
if(p[a][i]==p[b][i])continue;
else a=p[a][i],b=p[b][i];
}
return p[a][0];
}
int main()
{
int x,y;
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(s,0);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
}
tarjan缩点
#include<iostream>
#include <cstdio>
#include <stack>
using namespace std;
#define N 10000
int n,m;
struct ahah
{
int nxt,to;
} edge[N];
int head[N],tot;
void add(int x,int y)
{
edge[++tot].nxt=head[x],edge[tot].to=y;
head[x]=tot;
}
int index,dfn[N],low[N];
stack <int> S;
bool in[N];
int belong[N],cnt;
void tarjan(int u)
{
dfn[u]=low[u]=++index;
in[u]=1;
S.push(u) ;
for(int i=head[u]; i; i=edge[i].nxt)
{
int v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
if(low[v]<low[u])low[u]=low[v];
}
else if(in[v]&&dfn[v]<low[u])low[u]=dfn[v];
}
if(dfn[u]==low[u])
{
++cnt;
int p;
do
{
p=S.top();
S.pop() ;
in[p]=0;
belong[p]=cnt;
}
while(p!=u);
}
}
int main()
{
int x,y;
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)scanf("%d%d",&x,&y),add(x,y);
for(int i=1; i<=n; i++)if(!dfn[i])tarjan(i);
for(int i=1; i<=n; i++)printf("%d:%d ",i,belong[i]);
}
单源最短路
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int maxn=1e6+10;
const int maxm=2*maxn;
struct Edge
{
int u,v,w;
} edge[maxm];
int head[maxn],cnt;
inline void add(int u,int v,int w)
{
edge[++cnt].u=head[u],edge[cnt].v=v,edge[cnt].w=w,head[u]=cnt;
}
int dis[maxn],vis[maxn];
queue<int>q;
int n,m;
inline void spfa(int s)
{
for(int i=0;i<maxn;i++){
dis[i]=2147483647;
}
memset(vis,0,sizeof(vis));
dis[s]=0,vis[s]=1,q.push(s);
while(!q.empty())
{
int cur=q.front();
q.pop(),vis[cur]=0;
for(int i=head[cur]; i; i=edge[i].u)
{
int v=edge[i].v;
if(dis[v]>dis[cur]+edge[i].w)
{
dis[v]=dis[cur]+edge[i].w;
if(!vis[v])vis[v]=1,q.push(v);
}
}
}
for(int i=1; i<=n; i++) printf("%d ",dis[i]);
}
int main()
{
int u,v,w,s;
scanf("%d%d%d",&n,&m,&s);
while(m--)scanf("%d%d%d",&u,&v,&w),add(u,v,w);
spfa(s);
return 0;
}
最小生成树
#include<bits/stdc++.h>
using namespace std;
int m,n,k,fa[5001],xixi[2001],ans,sum;
struct ahah
{
int nxt,to,w;
} lol[200001];
bool cmp(ahah a,ahah b)
{
return a.w<b.w;
}
int find(int x)
{
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]);
}
int main()
{
scanf("%d%d",&n,&m);
int x,y,z;
for(int i=1; i<=n; i++)fa[i]=i;
for(int i=1; i<=m; i++)
{
cin>>x>>y>>z;
lol[i].nxt=x;
lol[i].to=y;
lol[i].w=z;
}
sort(lol,lol+1+m,cmp);
for(int i=1; i<=m; i++)
{
int g=find(lol[i].nxt);
int h=find(lol[i].to);
if(g!=h)
{
sum+=lol[i].w;
ans++;
if(ans==n-1)break;
fa[g]=h;
}
}
cout<<sum;
}
AC自动机
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct trie
{ int ch[26],f,x;
}a[200005];
char T[100005],S[100005];
int n,t;
queue<int>q;
int main()
{ scanf("%d",&n);
t=1;
while(n--)
{ scanf("%s",S+1);
int l=strlen(S+1),p=1;
for(int i=1;i<=l;i++)
{ int c=S[i]-'a';
if(!a[p].ch[c])a[p].ch[c]=++t;
p=a[p].ch[c];
}
++a[p].x;
}
for(int i=0;i<26;i++)
{ if(a[1].ch[i])
{ a[a[1].ch[i]].f=1;
q.push(a[1].ch[i]);
}else a[1].ch[i]=1;
}
while(!q.empty())
{ int u=q.front();q.pop();
for(int i=0;i<26;i++)
if(a[u].ch[i])
{ a[a[u].ch[i]].f=a[a[u].f].ch[i];
q.push(a[u].ch[i]);
}else a[u].ch[i]=a[a[u].f].ch[i];
}
return 0;
}
二·数据结构部分
(一)并查集
#include<bits/stdc++.h>
using namespace std;
int m,n,fa[200001];
int find(int x)
{
return fa[x]==x?x:fa[x]=find[fa[x]];
}
int main()
{
cin>>m>>n;
for(int i=1; i<=m; i++)fa[i]=i;
int x,y,z;
for(int i=1; i<=n; i++)
{
scanf("%d%d%d",&x,&y,&z);
if(x==1)
{
int g=find(y);
int h=find(z);
if(g!=h)fa[g]=h;
}
if(x==2)
{
int g=find(y);
int h=find(z);
if(g==h)cout<<"Y\n";
else cout<<"N\n";
}
}
}
(二)堆STL
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define mian main
#define N int(1e6+2)
using namespace std;
priority_queue <int,vector<int>,greater<int> >heap;
int n,a[N],now;
int f,k;
int main()
{
scanf("%d",&n);
while(n--)
{
scanf("%d",&f);
if(f==1)
{
scanf("%d",&k);
heap.push(k);
}
else if(f==2)printf("%d\n",heap.top());
else heap.pop() ;
}
}
(三)线段树
#include<cstdio>
#include<iostream>
using namespace std;
long long n,m,ans,x,y,ch,val;
struct ahah{
long long l,r,sum,f;
}tree[200000<<2];
void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;
if(tree[k].l==tree[k].r)
{
scanf("%lld",&tree[k].sum);
return ;
}
long long mid=(tree[k].l+tree[k].r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
void update(int k)
{
if(tree[k].l==tree[k].r)
{
tree[k].sum+=y;
return ;
}
long long mid=(tree[k].l+tree[k].r)>>1;
if(x<=mid)update(k<<1);
else update(k<<1|1);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
void down(long long k)
{
tree[k<<1].f+=tree[k].f;
tree[k<<1|1].f+=tree[k].f;
tree[k<<1].sum+=(tree[k<<1].r-tree[k<<1].l+1)*tree[k].f;
tree[k<<1|1].sum+=(tree[k<<1|1].r-tree[k<<1|1].l+1)*tree[k].f;
tree[k].f=0;
}
void query(int k)
{
if(x<=tree[k].l&&y>=tree[k].r)
{
ans+=tree[k].sum;
return ;
}
if(tree[k].f)down(k);
long long mid=(tree[k].l+tree[k].r)>>1;
if(x<=mid)query(k<<1);
if(y>mid)query(k<<1|1);
}
void add(long long k)
{
if(tree[k].l>=x&&tree[k].r<=y)
{
tree[k].sum+=(tree[k].r-tree[k].l+1)*val;
tree[k].f+=val;
return ;
}
if(tree[k].f) down(k);
long long mid=(tree[k].l+tree[k].r)>>1;
if(x<=mid)add(k<<1);
if(y>mid)add(k<<1|1);
tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}
int main()
{
scanf("%lld%lld",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++)
{
ans=0;
cin>>ch>>x>>y;
if(ch==1)
{
cin>>val;
add(1);
}
else
{
query(1);
cout<<ans<<"\n";
}
}
}
(四)2B平衡树
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct tree
{ int lc,rc,rt;
}a[100005];
int b[50005],cnt,t,n,m,q,x,y,z,ac;
int ch[2000005][2],f[2000005],w[2000005],sum[2000005];
inline int getwh(int u){return ch[f[u]][0]==u?0:1;}
inline void rotate(int u)
{ int fa=f[u],gr=f[fa],wh=getwh(u);
f[u]=gr;
ch[gr][getwh(fa)]=u;
f[ch[u][wh^1]]=fa;
ch[fa][wh]=ch[u][wh^1];
f[fa]=u;
ch[u][wh^1]=fa;
sum[fa]=sum[ch[fa][0]]+sum[ch[fa][1]]+1;
sum[u]=sum[ch[u][0]]+sum[ch[u][1]]+1;
}
inline void splay(int &root,int u)
{ while(f[u])
{ if(f[f[u]])
{ if(getwh(u)==getwh(f[u]))rotate(f[u]);
else rotate(u);
}
rotate(u);
}
root=u;
f[u]=0;
}
inline void ins(int &root,int x)
{ int last,now=root;
while(now)
{ last=now;
++sum[last];
if(x<=w[now])now=ch[now][0];
else now=ch[now][1];
}
ch[last][x<=w[last]?0:1]=++t;
f[t]=last;
w[t]=x;
sum[t]=1;
ch[t][0]=ch[t][1]=0;
splay(root,t);
}
inline int find(int &root,int x)
{ int now=root;
while(w[now]!=x)
{ if(x<w[now])now=ch[now][0];
else now=ch[now][1];
}
return now;
}
inline void del(int &root,int x)
{ splay(root,find(root,x));
if(ch[root][0]==0)
{ root=ch[root][1];
f[root]=0;
return;
}
if(ch[root][1]==0)
{ root=ch[root][0];
f[root]=0;
return;
}
int l=ch[root][0],r=ch[root][1],last;
root=ch[root][1];
f[root]=0;
while(ch[r][0])sum[r]+=sum[l],r=ch[r][0];
sum[r]+=sum[l];
ch[r][0]=l;
f[l]=r;
}
inline int getrank(int &root,int x)
{ int ac=0,now=root;
while(now)
{ if(x>w[now])
{ ac+=sum[ch[now][0]]+1;
now=ch[now][1];
}else now=ch[now][0];
}
return ac;
}
inline int getpre(int &root,int x)
{ int ac=-1,now=root;
while(now)
{ if(w[now]<x)
{ ac=w[now];
now=ch[now][1];
}else now=ch[now][0];
}
return ac;
}
inline int getnxt(int &root,int x)
{ int ac=1e8+1,now=root;
while(now)
{ if(w[now]>x)
{ ac=w[now];
now=ch[now][0];
}else now=ch[now][1];
}
return ac;
}
void build(int u,int l,int r)
{ a[u].rt=++t;
ch[t][0]=ch[t][1]=f[t]=0;
w[t]=b[l];
sum[t]=1;
for(int i=l+1;i<=r;i++)ins(a[u].rt,b[i]);
if(l==r)return;
int mid=(l+r)>>1;
a[u].lc=++cnt;
build(cnt,l,mid);
a[u].rc=++cnt;
build(cnt,mid+1,r);
}
void segrank(int u,int l,int r,int ll,int rr,int w)
{ if(l==ll&&r==rr)
{ ac+=getrank(a[u].rt,w);
return;
}
int mid=(l+r)>>1;
if(rr<=mid)segrank(a[u].lc,l,mid,ll,rr,w);
else if(ll>mid)segrank(a[u].rc,mid+1,r,ll,rr,w);
else
{ segrank(a[u].lc,l,mid,ll,mid,w);
segrank(a[u].rc,mid+1,r,mid+1,rr,w);
}
}
inline int rankinlr(int w,int l,int r)
{ ac=0;
segrank(1,1,n,l,r,w);
return ac+1;
}
void updata(int u,int l,int r,int x,int ww)
{ if(l==r)
{ a[u].rt=++t;
ch[t][0]=ch[t][1]=f[t]=0;
w[t]=ww;
sum[t]=1;
return;
}
del(a[u].rt,b[x]);
ins(a[u].rt,ww);
int mid=(l+r)>>1;
if(x<=mid)updata(a[u].lc,l,mid,x,ww);
else updata(a[u].rc,mid+1,r,x,ww);
}
void segpre(int u,int l,int r,int ll,int rr,int w)
{ if(l==ll&&r==rr)
{ ac=max(ac,getpre(a[u].rt,w));
return;
}
int mid=(l+r)>>1;
if(rr<=mid)segpre(a[u].lc,l,mid,ll,rr,w);
else if(ll>mid)segpre(a[u].rc,mid+1,r,ll,rr,w);
else
{ segpre(a[u].lc,l,mid,ll,mid,w);
segpre(a[u].rc,mid+1,r,mid+1,rr,w);
}
}
void segnxt(int u,int l,int r,int ll,int rr,int w)
{ if(l==ll&&r==rr)
{ ac=min(ac,getnxt(a[u].rt,w));
return;
}
int mid=(l+r)>>1;
if(rr<=mid)segnxt(a[u].lc,l,mid,ll,rr,w);
else if(ll>mid)segnxt(a[u].rc,mid+1,r,ll,rr,w);
else
{ segnxt(a[u].lc,l,mid,ll,mid,w);
segnxt(a[u].rc,mid+1,r,mid+1,rr,w);
}
}
int main()
{ scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&b[i]);
cnt=1;
t=0;
build(1,1,n);
while(m--)
{ scanf("%d%d%d",&q,&x,&y);
if(q!=3)scanf("%d",&z);
if(q==1)printf("%d\n",rankinlr(z,x,y));
if(q==2)
{ int l=0,r=1e8+1;
while(r-l>1)
{ int mid=(l+r)>>1;
if(rankinlr(mid,x,y)<=z)l=mid;else r=mid;
}
printf("%d\n",l);
}
if(q==3)
{ updata(1,1,n,x,y);
b[x]=y;
}
if(q==4)
{ ac=-1;
segpre(1,1,n,x,y,z);
printf("%d\n",ac);
}
if(q==5)
{ ac=1e8+1;
segnxt(1,1,n,x,y,z);
printf("%d\n",ac);
}
}
return 0;
}
(五)splay
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,a[100005];
struct Splay
{ int rt,f[100005],ch[100005][2],sum[100005],t;
int build(int l,int r)
{ int mid=(l+r)>>1;
sum[mid]=r-l+1;
ch[mid][0]=l<mid?build(l,mid-1):0;
ch[mid][1]=mid<r?build(mid+1,r):0;
f[ch[mid][0]]=f[ch[mid][1]]=mid;
return mid;
}
inline int getwh(int u){return ch[f[u]][0]==u?0:1;}
inline void rotate(int u)
{ int fa=f[u],gr=f[fa],wh=getwh(u);
f[u]=gr;
ch[gr][getwh(fa)]=u;
f[ch[u][wh^1]]=fa;
ch[fa][wh]=ch[u][wh^1];
f[fa]=u;
ch[u][wh^1]=fa;
sum[fa]=sum[ch[fa][0]]+sum[ch[fa][1]]+1;
sum[u]=sum[ch[u][0]]+sum[ch[u][1]]+1;
}
inline void splay(int u,int tar)
{ while(f[u]!=tar)
{ if(f[f[u]]!=tar)
{ if(getwh(u)==getwh(f[u]))rotate(f[u]);
else rotate(u);
}
rotate(u);
}
if(!tar)rt=u;
}
int findkth(int key)
{ int o=rt;
while(1)
{ if(sum[ch[o][0]]+1==key)return o;
if(key<=sum[ch[o][0]])o=ch[o][0];
else
{ key-=sum[ch[o][0]]+1;
o=ch[o][1];
}
}
}
int getrank(int key)
{ int o=rt,ac=0;
while(o)
{ if(a[o]<key)
{ ac+=sum[ch[o][0]]+1;
o=ch[o][1];
}else o=ch[o][0];
}
return ac+1;
}
void merge(int x,int y)
{ if(x==0){rt=y;return;}
if(y==0){rt=x;return;}
while(ch[y][0])
{ sum[y]+=sum[x];
y=ch[y][0];
}
sum[y]+=sum[x];
ch[y][0]=x,f[x]=y;
splay(x,0);
}
void ins(int w)
{ a[++t]=w,sum[t]=1;
if(rt==0)
{ rt=t;
return;
}
int o=rt,last;
while(o)
{ ++sum[last=o];
if(w<a[o])o=ch[o][0];
else o=ch[o][1];
}
f[t]=last,ch[last][w<a[last]?0:1]=t;
splay(t,0);
}
void del(int u)
{ splay(u,0);
f[ch[u][0]]=f[ch[u][1]]=0;
merge(ch[u][0],ch[u][1]);
}
}splay;
int main()
{ scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
splay.rt=splay.build(1,n);
splay.t=n;
return 0;
}
数学数论部分
(一)筛素数
埃拉托斯特尼筛法
memset(check, 0, sizeof(check));
int tot = 0;
for (int i = 2; i <= n; ++i)
{
if (!check[i])
{
prime[tot++] = i;
}
for (int j = i+i; j <= n; j += i)
{
check[j] = 1;
}
}
线性筛
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;
#define N int(1e7+2)
#define M int(5e5+2)
#define L 2147483647
int n,m;
bool prime[N];
int f[N],tot;
int read()
{
int sum=0,fg=1; char c=getchar();
while(c<'0'||c>'9'){if(c=='-')fg=-1;c=getchar();}
while(c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}
return sum*fg;
}
void _prime()
{
for(int i=1;i<=n;i++)prime[i]=1;
prime[1]=0;
for(int i=2;i<=n/2;i++)
{
if(prime[i])f[++tot]=i;
for(int j=1;j<=tot&&f[j]*i<=n;j++)
{
prime[f[j]*i]=0;
if(i%f[j]==0)break;
}
}
}
int main()
{
int x;
n=read(),m=read();
_prime();
while(m--)
{
x=read();
if(prime[x])printf("Yes\n");
else printf("No\n");
}
}
(二)组合数递推
for(int i=1; i<=2001; i++)
{
f[i][0]=1,f[i][i]=1;
for(int j=1; j<i; j++)f[i][j]=(f[i-1][j-1]+f[i-1][j])%k;
}
(三)最小公约数与最大公倍数
#include <iostream>
using namespace std;
int main()
{
int m,n,r,t;
cout<<"请输入两个值,求最小公倍数"<<endl;
cin>>m>>n;
int a = m; //先把m、n保存一份
int b = n;
if(m<n)
{
t=m; //用分号
m=n; //用分号
n=t;
}
while((r=m%n)!=0)
{
m=n;
n=r;
}
cout<<"最大公约数="<< n << endl;
cout<<"最小公倍数="<< a * b / n << endl; //最后这样打印
}
(四)欧几里得扩展
#include <cstdio>
int exgcd(int a, int b, int &x, int &y) //非递归版
{
int d;
if (!b) x = 1, y = 0, d = a;
else
{
d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
}
return d;
}
int exgcd(int a, int b, int &x, int &y) //递归版
{
int d;
return !b ? (x = 1, y = 0, a) : (d = exgcd(b, a % b, y, x), y -= (a / b) * x, d);
}
int main()
{
int a, b, x, y;
scanf ("%d%d", &a, &b);
printf("%d\n", exgcd(a, b, x, y));
printf("%d %d\n", x, y);
}
(五)高斯消元
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-8;
int n;
double a[111][111];
double b[111];
double ans[111];
int sign(double x)
{
if(fabs(x)<=eps)return 0;
if(x>0)return 1;
return -1;
}
int main()
{
// printf("%lf",eps);
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n+1;j++)scanf("%lf",&a[i][j]);
}
// cout<<n<<"\n";
for(int i=1;i<=n;i++)
{
if(fabs(a[i][i])<=eps)
{
printf("No Solution\n");
return 0;
}
int p=i;
for(int j=i;j<=n;j++)
{
if(fabs(a[j][i])>fabs(a[p][i]))p=j;
}
for(int j=1;j<=n+1;j++)swap(a[i][j],a[p][j]);
// swap(b[i],b[p]);
for(int j=i+1;j<=n;j++)
{
double ratio=a[j][i]/a[i][i];
for(int k=1;k<=n+1;k++)a[j][k]=a[j][k]-a[i][k]*ratio;
}
// for(int j=1;j<=n;j++)printf("%lfX1+%lfX2+%lfX3=%lf\n",a[j][1],a[j][2],a[j][3],a[j][4]);cout<<"\n";
}
for(int i=n;i>=1;i--)
{
for(int j=n;j>i;j--)
{
if(sign(a[i][j])==0)break;
a[i][n+1]-=ans[j]*a[i][j];
}
ans[i]=a[i][n+1]/a[i][i];
}
for(int i=1;i<=n;i++)printf("%.2lf\n",ans[i]);
}
(六)卢卡斯定理
#include <cstdio>
#include <cctype>
typedef long long LL;
#define dd c=getchar()
inline void read(LL &x)
{
x=0;
char dd;
bool f=false;
for(; !isdigit(c); dd)if(c=='-')f=true;
for(; isdigit(c); dd) x=(x<<1)+(x<<3)+(c^48);
if(f)x=-x;
return;
}
typedef long long LL;
LL mod;
inline LL pow(LL a,LL b)//快速幂是为了求逆元
{
LL ans=1;
for(; b; b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;
return ans;
}
LL farc[1000005];
inline void prepare(LL a)
{
farc[0]=1;
for(LL i=1; i<=a; ++i)farc[i]=farc[i-1]*i%mod;
}
inline LL Csmall(LL m,LL n)//C(m,n)=(n!)/(m!*(n-m)!)
{
if(n<m)return 0;
return farc[n]*pow(farc[m],mod-2)%mod*pow(farc[n-m],mod-2)%mod;//费马小定理求逆元
}
/*递归形式
inline LL C(LL m,LL n)
{
if(n<m) return 0;
if(!n) return 1;//Lucas的边界条件
return C(m/mod,n/mod)%mod*Csmall(m%mod,n%mod)%mod;//上面证明的Lucas定理
}
*/
inline LL C(LL m,LL n)
{
LL ans=1;
while(n&&m&&ans)
{
ans=(ans*Csmall(m%mod,n%mod))%mod;
n/=mod,m/=mod;
}
return ans;
}
int main()
{
LL T;
read(T);
while(T--)
{
LL m,n;
read(m);
read(n);
read(mod);
prepare(m+n);
printf("%lld\n",C(n,m+n));
}
return 0;
}