模板大全(仅限个人能力)

模板大全

一·算法部分

 

(一)排序部分

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]);
}
View Code

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]);
}
View Code

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]);
}
View Code

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]);
} 
View Code

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;
}
View Code

(三)三分

#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);
}
View Code

(四)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;
}
View Code

(五)字符串相关

#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]<<" ";
}
manacher算法
#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;
}
kmp字符串匹配
#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;
}
字符串hash

 

(六)网络流

#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;
}
网络最大流

(七)树图相关

#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));
    }
}
倍增LCA
#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]);
}
tarjan缩点
#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;
}
最小生成树
#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;
}
AC自动机
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#define LL long long
using namespace std;
const int maxn=1e5+2;
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> > Q;
struct ahah{
    int nxt,to,dis;
}edge[maxn*2];
int head[maxn],tot;
int d[maxn];
bool vis[maxn];
void add(int x,int y,int z)
{
    edge[++tot].nxt=head[x];edge[tot].to=y;edge[tot].dis=z;head[x]=tot;
}
int n,m,s;
void dijkstra(int s)
{
    for(int i=1;i<=n;i++)d[i]=1234567890;
    Q.push(make_pair(0,s));
    d[s]=0;
    while(!Q.empty())
    {
        while(!Q.empty()&&vis[Q.top().second])Q.pop();
        if(Q.empty())return;
        int temp=Q.top().second;
        d[temp]=Q.top().first;
        vis[temp]=1;
        Q.pop();
        for(int i=head[temp];i;i=edge[i].nxt)
        {
            if(!vis[edge[i].to])Q.push(make_pair(d[temp]+edge[i].dis,edge[i].to));
        }
    }
}
int main()
{
    cin>>n>>m>>s;
    int x,y,z;
    for(int i=1;i<=m;i++)
    {
        cin>>x>>y>>z;
        add(x,y,z);
//        add(y,x,z);
    }
    dijkstra(s);
    for(int i=1;i<=n;i++)cout<<d[i]<<" ";
}
单源最短路

 

二·数据结构部分

(一)并查集

#include<bits/stdc++.h>
using namespace std;
int m,n,fa[200001];
int find(int x)
{
    if(fa[x]==x)return x;
    else return 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";
        }
    }
}
View Code

(二)堆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() ;
    }
}
View Code

(三)线段树

#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";
        }
    }
}
View Code

(四)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;
}
View Code

(五)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;
}
View Code

 

数学数论部分

(一)筛素数

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;
}
View Code

(三)最小公约数与最大公倍数

#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;  //最后这样打印 
}
View Code

(四)欧几里得扩展

#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);
}
View Code

(五)高斯消元

#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]);
}
View Code

(六)卢卡斯定理

#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;
}
View Code

 

目前整理就这么多了,以后会持续更新

posted @ 2018-08-03 22:04  Manjusaka丶梦寒  阅读(737)  评论(3编辑  收藏  举报