ACM&&OI模板

各种算法的模板整理

蒟蒻的模板 可能不是很好

============================================================

基础类


  • 快速排序【2018.3.10】
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int M=1e6+10;
namespace QSort{
   int size;
template <class T>
  void swap(T &a,T &b){T t=a;a=b;b=t;}
template <class T>
  void Qsort(T a,T b,T *c)
   {
        if(a==b) return;
        T mid=(a+b)/2;
        T val=c[mid];
        T i=a-1,j=b+1;
        while(1)
        {
            do i++;while(c[i]<val);
            do j--;while(c[j]>val);
            if(i>=j) break;
            swap(c[i],c[j]);
        }
        Qsort(a,j,c);
        Qsort(j+1,b,c);
   }
}
using namespace QSort;
int x[M];
void init(){
   scanf("%d",&size);
   for(int i=1;i<=size;i++)scanf("%d",&x[i]);
}
void out(){
   Qsort(1,size,x);
   for(int i=1;i<=size;i++)printf("%d ",x[i]);
}
int main(){
    init();
    out();
    return 0;
}

  • 归并排序 【2018.3.10】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e6+10;
namespace GSort{
    int size;
template <class T>
  void Gsort(T a,T b,T *c,T *d)
  {
     if(a==b) return;
     T mid=(a+b)/2;
     Gsort(a,mid,c,d);
     Gsort(mid+1,b,c,d);
     int f=a,f1=a,f2=mid+1;
     while(f1<=mid&&f2<=b){
        if(d[f1]<d[f2])c[f++]=d[f1++];
        else           c[f++]=d[f2++];
     }
     for(T i=f1;i<=mid;i++)c[f++]=d[i];
     for(T i=f2;i<=b;i++)  c[f++]=d[i];
     for(T i=a;i<=b;i++)   d[i]  =c[i];
  }
}
using namespace GSort;
int td[M],x[M];
void init(){
   scanf("%d",&size);
   for(int i=1;i<=size;i++)scanf("%d",&x[i]);
}
void out(){
   Gsort(1,size,td,x);
   for(int i=1;i<=size;i++)printf("%d ",x[i]);
}
int main(){
    init();
    out();
    return 0;
}

图论


  • 最小生成树-Kruskal【2018.3.12】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=2e5+10,N=5010;
int n,m;
struct ss{
    int from,to,val;
    ss(int a=0,int b=0,int c=0):from(a),to(b),val(c){}
    bool operator <(ss a)const{return val<a.val;}
}g[M];
struct ufs{
    int f[N];
    int find(int a){return f[a]==a?a:f[a]=find(f[a]);}
    void init(){for(int i=1;i<=n;i++)f[i]=i;}
    void uni(int a,int b){f[a]=b;}
}uf;
void readin(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&g[i].from,&g[i].to,&g[i].val);
}
int Kruskal(){
    sort(g+1,g+m+1);
    uf.init();
    int tot=0,ans=0;
    for(int i=1;i<=m;i++){
        int a=uf.find(g[i].from),b=uf.find(g[i].to);
        if(a==b) continue;
        uf.uni(a,b);
        tot++;ans+=g[i].val;
        if(tot==n-1) break;
    }
    return ans;
}
int main()
{
    readin();
    printf("%d\n",Kruskal());
    return 0;
}

Before 风格

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e5+10;
struct ss{
    int from,to,cap;
    bool operator <(ss a)const{return cap<a.cap;}
}g[M<<1];
int f[M];
int n,m;
int find(int a){return f[a]==a?a:f[a]=find(f[a]);}
void init(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) f[i]=i;
}
int main()
{
    init();
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&g[i].from,&g[i].to,&g[i].cap);
    }
    sort(g+1,g+m+1);
    int tot=0,ans=0;
    for(int i=1;i<=m;i++){
        int f1=find(g[i].from),f2=find(g[i].to);
        if(f1==f2) continue;
        f[f1]=f2;
        ans+=g[i].cap;tot++;
        if(tot==n-1) break;
    }
    printf("%d\n",ans);
    return 0;
}

  • 最大流-Dinic 【2018.3.13】
    • 前向星存图(链表)
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=1e5+10;
int n,m,s,t;
struct ss{
    int to,last,cap;
    ss(int a=0,int b=0,int c=0):to(a),last(b),cap(c){}
}g[M<<1];
int head[M],cnt=1;
void add(int a,int b,int c){
    g[++cnt]=ss(b,head[a],c);head[a]=cnt;
    g[++cnt]=ss(a,head[b],0);head[b]=cnt;
}
int dep[M],cur[M],que[M],p,q;
int bfs(){
    memset(dep,0,sizeof(dep));
    dep[s]=1;que[p=q=1]=s;
    for(;p<=q;p++){
        int now=que[p];
        for(int i=head[now];i;i=g[i].last){
            if(!dep[g[i].to]&&g[i].cap>0){
                dep[g[i].to]=dep[now]+1;
                que[++q]=g[i].to;
            }
        }
    }
    return dep[t];
}
int dfs(int a,int cap){
    if(a==t||cap<0) return cap;
    int tot=0;
    if(!cur[a]) cur[a]=head[a];
    for(int &i=cur[a];i;i=g[i].last){
        if(g[i].cap>0&&dep[g[i].to]==dep[a]+1){
            int now=dfs(g[i].to,min(g[i].cap,cap));
            tot+=now;cap-=now;
            g[i].cap-=now;g[i^1].cap+=now;
            if(cap<=0) break;
        }
    }
    return tot;
}
const int inf=0x7fffffff;
int maxflow(){
    int ans=0;
    while(bfs()){
        memset(cur,0,sizeof(cur));
        ans+=dfs(s,inf);
    }
    return ans;
}
int a,b,c;
void readin(){
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
}
int main()
{
    readin();
    printf("%d\n",maxflow());
    return 0;
}
  • 邻接表存图(vector)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std;
const int M=6e5+10,N=1010,inf=0x7fffffff;
int cal[N],que[N],p,q,dep[N],cnt=1;
int n,m,st,en,ans;
struct ss{
    int to,cap;
    ss(int a=0,int b=0):to(a),cap(b){}
}g[M];
vector <int> vec[N];
void add(int a,int b,int c){
    g[++cnt]=ss(b,c);vec[a].push_back(cnt);
    g[++cnt]=ss(a,0);vec[b].push_back(cnt);
}
int bfs(){
    memset(dep,0,sizeof(dep));
    dep[st]=1;que[p=q=1]=st;
    for(;p<=q;p++){
        int now=que[p];
        for(int i=0;i<(int)vec[now].size();i++){
            int t=vec[now][i];
            if(!dep[g[t].to]&&g[t].cap){
                dep[g[t].to]=dep[now]+1;
                que[++q]=g[t].to;
            }
        }
    }
    return dep[en];
}
int dfs(int a,int cap){
    if(a==en||!cap) return cap;
    int tot=0;
    for(int &i=cal[a];i<vec[a].size();i++){
        int t=vec[a][i];
        if(dep[g[t].to]==dep[a]+1&&g[t].cap){
            int now=dfs(g[t].to,min(cap,g[t].cap));
            g[t].cap-=now;g[t^1].cap+=now;
            tot+=now;
            cap-=now;
            if(!cap) break;
        }
    }
    return tot;
}
int a,b,c;
int read(){
    int x=0;char ch=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') {
        x=(x<<3)+(x<<1)+ch-'0';ch=getchar();
    }
    return x;
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&st,&en);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a,&b,&c);
        add(a,b,c);
    }
    while(bfs()){
        memset(cal,0,sizeof(cal));
        int now;
        while(now=dfs(st,inf)) ans+=now;
    }
    printf("%d\n",ans);
    return 0;
}

  • 并查集【2018.3.15】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=2e5+10;
namespace BCJ{
template <class T>
    struct bcj{
        T f[M];
        T find(T a){return f[a]==a?a:f[a]=find(f[a]);}
        T operator [](T a){return find(a);}
        void clear(){memset(f,0,sizeof(f));}
        void init(T a){for(T i=0;i<=a;i++)f[i]=i;}
    };
    void merge(bcj <int> &a,int t1,int t2){
        int f1=a[t1],f2=a[t2];
        if(f1==f2) return;
        a.f[f1]=f2;
    }
}
using namespace BCJ;
bcj <int> f;
int n,m,a,b,c;
int main()
{
    scanf("%d%d",&n,&m);
    f.init(n);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a,&b,&c);
        switch(a){
            case 1:{
                merge(f,b,c);
                break;
            }
            case 2:{
                if(f[b]==f[c]) printf("Y\n");
                else printf("N\n");
                break;
            }
        }
    }
    return 0;
}
  • 并查集【以前的风格】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=2e5+10;
int n,m;
int f[M];
int find(int a){return f[a]==a?a:f[a]=find(f[a]);}
void init(){for(int i=1;i<=n;i++)f[i]=i;}
int cao,a,b;
int main(){
    scanf("%d%d",&n,&m);
    init();
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&cao,&a,&b);
        int p1=find(a),p2=find(b);
        if(cao==2){
            if(p1==p2) printf("Y\n");
            else printf("N\n");
        }else{
            f[p1]=p2;
        }
    }
    return 0;
}

  • LCA【2018.3.19】

  • Tarjan离线算法

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=5e5+10;
struct ss{
    int to,last;
    ss(int a=0,int b=0):to(a),last(b){}
}g[M<<1];
struct que{
    int to,last,lca;
    que(int a=0,int b=0,int c=0):to(a),last(b),lca(c){}
}q[M<<1];
int headg[M],headq[M],n,m,root,a,b;
int cnt,tot=1;
int f[M];
int find(int a){return f[a]==a?a:f[a]=find(f[a]);}
void add1(int a,int b){
    g[++cnt]=ss(b,headg[a]);headg[a]=cnt;
    g[++cnt]=ss(a,headg[b]);headg[b]=cnt;
}
void add2(int a,int b){
    q[++tot]=que(b,headq[a]);headq[a]=tot;
    q[++tot]=que(a,headq[b]);headq[b]=tot;
}
bool vis[M];
void dfs(int a){
    f[a]=a;vis[f[a]]=1;
    for(int i=headg[a];i;i=g[i].last){
        if(vis[g[i].to]) continue;
        dfs(g[i].to);f[g[i].to]=a;
    }
    for(int i=headq[a];i;i=q[i].last){
        if(vis[q[i].to]){
            q[i^1].lca=q[i].lca=find(q[i].to);
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&root);
    for(int i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        add1(a,b);
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        add2(a,b);
    }
    dfs(root);
    for(int i=1;i<=m;i++)printf("%d\n",q[i<<1].lca);
    return 0;
}
  • 倍增的在线算法
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=5e5+10;
int n,m,root;
int f[M][22];
struct ss{
    int to,last;
    ss(int a=0,int b=0):to(a),last(b){}
}g[M<<1];
int head[M],cnt;
void add(int a,int b){
    g[++cnt]=ss(b,head[a]);head[a]=cnt;
    g[++cnt]=ss(a,head[b]);head[b]=cnt;
}
int dep[M];
void dfs(int a,int fa,int dp){
    dep[a]=dp;
    f[a][0]=fa;
    for(int i=1;i<=21;i++){f[a][i]=f[f[a][i-1]][i-1];}
    for(int i=head[a];i;i=g[i].last){
        if(g[i].to==fa) continue;
        dfs(g[i].to,a,dp+1);
    }
}
void swap(int &a,int &b){a^=b^=a^=b;}
int lca(int a,int b){
    if(dep[a]<dep[b]) swap(a,b);
    for(int i=21;i>=0;i--){
        if(dep[f[a][i]]>=dep[b]){
            a=f[a][i];
        }
    }
    if(a==b) return a;
    for(int i=21;i>=0;i--){
        if(f[a][i]!=f[b][i]){
            a=f[a][i];
            b=f[b][i];
        }
    }
    return f[a][0];
}
int a,b;
int main()
{
    scanf("%d%d%d",&n,&m,&root);
    for(int i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        add(a,b);
    }
    dfs(root,0,1);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        printf("%d\n",lca(a,b));
    }
    return 0;
}

  • 最小费用最大流SPFA【2018.3.31】
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=1e5+10;
const int inf=0x7fffffff;
int n,m,s,t;

struct ss{
    int to,last,cap,cost;
    ss(int a=0,int b=0,int c=0,int d=0):to(a),last(b),cap(c),cost(d){}
}g[M<<1];
int head[M],cnt=1;
void add(int a,int b,int c,int d){
    g[++cnt]=ss(b,head[a],c,d);head[a]=cnt;
    g[++cnt]=ss(a,head[b],0,-d);head[b]=cnt;
}
int dis[M],que[M],p,q,flow[M],from[M],pos[M];
bool used[M];
bool bfs(){
    for(int i=1;i<=n;i++){
        used[i]=flow[i]=from[i]=0;
        dis[i]=inf;
    }
    used[s]=1;flow[s]=inf;dis[s]=0;
    que[p=q=1]=s;
    for(;p<=q;p++){
        int now=que[p];
        used[now]=0;
        for(int i=head[now];i;i=g[i].last){
            if(dis[g[i].to]>dis[now]+g[i].cost&&g[i].cap>0){
                dis[g[i].to]=dis[now]+g[i].cost;
                from[g[i].to]=now;pos[g[i].to]=i;
                flow[g[i].to]=min(flow[now],g[i].cap);
                if(!used[g[i].to]){
                    used[g[i].to]=1;
                    que[++q]=g[i].to;
                    if(dis[que[(p+1)]]>dis[que[q]])
                    swap(que[(p+1)],que[q]);
                }
            }
        }
    }
    if(dis[t]==inf) return 0;return 1;
}
void work(){
    int mc=0,mf=0;
    while(bfs()){
        mc+=flow[t]*dis[t];
        mf+=flow[t];
        for(int i=t;i;i=from[i]){
            g[pos[i]].cap-=flow[t];
            g[pos[i]^1].cap+=flow[t];
        }
    }
    printf("%d %d\n",mf,mc);
}
int a,b,c,d;
int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&a,&b,&c,&d);
        add(a,b,c,d);
    }
    work();
    return 0;
}

数据结构


  • 堆(大根和小根)【2018.3.13】
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=1e6+10;
#define MIN
/*
  MIN 从小到大:小根堆
  MAX 从大到小:大根堆
*/
#include<iostream>
namespace Heap{
template <class T>
struct HEAP{
     T heap[M];int sze;
#ifdef MIN
/*Min*/
    void insert(T a){
        heap[++sze]=a;
        int fa=sze>>1,now=sze;
        while(fa){
            if(heap[fa]>heap[now]) swap(heap[fa],heap[now]);
            now=fa;fa=now>>1;
        }
    }
    void pop(){
        heap[1]=heap[sze];sze--;
        int son=2,now=1;
        while(son<=sze){
            if(son+1<=sze&&heap[son+1]<heap[son]) son++;
            if(heap[now]<heap[son]) break;
            else swap(heap[now],heap[son]);
            now=son,son=now<<1;
        }
    }
#endif

#ifndef MIN
#ifdef MAX
/*Max*/
    void insert(T a){
        heap[++sze]=a;
        int fa=sze>>1,now=sze;
        while(fa){
            if(heap[fa]<heap[now]) swap(heap[fa],heap[now]);
            now=fa;fa=now>>1;
          }
    }
    void pop(){
        heap[1]=heap[sze];sze--;
        int son=2,now=1;
        while(son<=sze){
            if(son+1<=sze&&heap[son+1]>heap[son]) son++;
            if(heap[now]>heap[son]) break;
            else swap(heap[now],heap[son]);
            now=son,son=now<<1;
        }
    }

#endif
#endif
    T top(){return heap[1];}
    void out(T *a,int begin,int end){for(int i=begin;i<=end;i++) a[i]=top(),pop();}
    int size(){return sze;}
    void sort(T *a,int begin,int end){
        for(int i=begin;i<=end;i++){insert(a[i]);}
        out(a,begin,end);
    }
    void clear(){memset(heap,0,sizeof(heap));sze=0;}
};
}
using namespace Heap;
HEAP <int> hp;
/*Luogu P1177排序*/
int n,x[M];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){scanf("%d",&x[i]);}
    hp.sort(x,1,n);
    for(int i=1;i<=n;i++) printf("%d ",x[i]);
    return 0;
}
/*Luogu P3378 堆*/
int n,cao,b;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&cao);
        switch(cao){
            case 1:{
                scanf("%d",&b);
                hp.insert(b);
                break;
            }
            case 2:{
                printf("%d\n",hp.top());
                break;
            }
            case 3:{
                hp.pop();
                break;
            }
        }
    }
    return 0;
}

  • 树状数组(全)【2018.3.16】
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=5e5+10;
namespace BITTREE{
    int lowbit(int a){return (a&(-a));}
/*普通的树状数组*/
template <class T>
struct bit_tree{
    T f[M];
    int sze;
    int size(){return sze;}
    void add_pos(int p,T a){
        for(int i=p;i<=sze;i+=lowbit(i))f[i]+=a;
    }
    void add_area(int l,int r,T a){
        add_pos(l,a);add_pos(r+1,-a);
    }
    T query_pos(int p){
        T ans=0;
        for(int i=p;i;i-=lowbit(i)) ans+=f[i];
        return ans;
    }
    T query_area(int l,int r){
        T ans=query_pos(r)-query_pos(l-1);
        return ans;
    }
    void clear(){memset(f,0,sizeof(f));}
    bit_tree(int a=1){if(!a)clear();}
    T operator [](int a){return query_pos(a);sze=0;}
};
/*树组树组维护区间最大值*/
template <class T>
struct max_tree{
    T maxv[M],v[M];
    int sze;
    int size(){return sze;}
    T max_area(int l,int r){
        T ans=0;
        while(l<=r){
            ans=max(ans,v[r]);r--;
            for(;r-lowbit(r)>=l;r-=lowbit(r)) ans=max(ans,maxv[r]);
        }
        return ans;
    }
    T change_pos(int p,T a){
        v[p]=a;
        for(int i=p;i<=sze;i+=lowbit(i)){
            maxv[i]=v[i];
            for(int j=1;j<lowbit(i);j<<=1) maxv[i]=max(maxv[i],maxv[i-j]);
        }
    }
    T operator [](int a){return v[a];}
    T operator ()(int a,int b){return max_area(a,b);}
    void init(int p){
        for(int i=p;i<=sze;i+=lowbit(i)) maxv[i]=max(maxv[i],v[p]);
    }
    void clear(){memset(maxv,0,sizeof(maxv));memset(v,0,sizeof(v));sze=0;}
};
/*二维树状数组*/
template <class T>
struct two_bit{
    T f[2000][2000];
    int sze1,sze2;
    void add_pos(int a,int b,T v){
        for(int i=a;i<=sze1;i+=lowbit(i))
        for(int j=b;j<=sze2;j+=lowbit(j))
        f[i][j]+=v;
    }
    T query_pos(int a,int b){
        T ans=0;
        for(int i=a;i;i-=lowbit(i))
        for(int j=b;j;j-=lowbit(j))
        ans+=f[i][j];
        return ans;
    }
    void add_area(int x1,int y1,int x2,int y2){
        add_pos(x1,y1,1);
        add_pos(x1,y2+1,-1);
        add_pos(x2+1,y1,-1);
        add_pos(x2+1,y2+1,1);
    }
    T operator ()(int a,int b){return query_pos(a,b);}
    void clear(){memset(f,0,sizeof(f));sze1=sze2=0;}
};
}
using namespace BITTREE;


/*Luogu P3368*/
//bit_tree <int> tr;
//int m,a,b,c,d;
//int main()
//{
//  scanf("%d%d",&tr.sze,&m);
//  for(int i=1;i<=tr.sze;i++){
//      scanf("%d",&a);
//      tr.add_area(i,i,a);
//  }
//  for(int i=1;i<=m;i++){
//      scanf("%d%d",&a,&b);
//      if(a==1){
//          scanf("%d%d",&c,&d);
//          tr.add_area(b,c,d);
//      }else{
//          printf("%d\n",tr[b]);
//      }
//  }
//  return 0;
//}

/*Luogu P3374*/
//bit_tree <int> tr;
//int m,a,b,c,d;
//int main()
//{
//  scanf("%d%d",&tr.sze,&m);
//  for(int i=1;i<=tr.sze;i++){
//      scanf("%d",&a);
//      tr.add_pos(i,a);
//  }
//  for(int i=1;i<=m;i++){
//      scanf("%d%d%d",&a,&b,&c);
//      if(a==1){
//          tr.add_pos(b,c);
//      }else{
//          printf("%d\n",tr.query_area(b,c));
//      }
//  }
//  return 0;
//}

/*HDU1754*/
//max_tree <int> tr2;
//int n,m,a,b;
//char cao[2];
//int main(){
//  while(scanf("%d%d",&n,&m)==2){
//      tr2.sze=n;
//      for(int i=1;i<=n;i++){
//          scanf("%d",&a);
//          tr2.v[i]=a;
//          tr2.init(i);
//      }
//      for(int i=1;i<=m;i++){
//          scanf("%s%d%d",cao,&a,&b);
//          if(cao[0]=='Q'){
//              printf("%d\n",tr2(a,b));
//          }else{
//              tr2.change_pos(a,b);
//          }
//      }
//      tr2.clear();
//  }
//  return 0;
//}

/*POJ2155*/
//int T,t1,t2,t3,t4,n,m;
//char cao[5];
//two_bit <int> tr;
//int main()
//{
//  scanf("%d",&T);
//  while(T--){
//      tr.clear();
//      scanf("%d%d",&n,&m);
//      tr.sze1=tr.sze2=n;
//      for(int i=1;i<=m;i++){
//          scanf("%s",cao);
//          if(cao[0]=='C'){
//              scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
//              tr.add_area(t1,t2,t3,t4);
//          }else{
//              scanf("%d%d",&t1,&t2);
//              printf("%d\n",tr(t1,t2)&1);
//          }
//      }
//      printf("\n");
//  }
//  return 0;
//}

  • 线段树1【2018.3.16】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e5+10;
namespace Segment_tree{
template <class T>
   struct segment_tree{
        int sze;
        T sumv[M<<2],v[M],lazy[M<<2];
        void pushup(int o){sumv[o]=sumv[o<<1]+sumv[o<<1|1];}
        void pushdown(int o,int l,int r){
            if(!lazy[o]) return;
            int mid=l+r>>1;
            lazy[o<<1]+=lazy[o];lazy[o<<1|1]+=lazy[o];
            sumv[o<<1]+=lazy[o]*(mid-l+1);
            sumv[o<<1|1]+=lazy[o]*(r-mid);
            lazy[o]=0;
        }
        void build(int o,int l,int r){
            lazy[o]=0;
            if(l==r){sumv[o]=v[l];return;}
            int mid=l+r>>1;
            build(o<<1,l,mid);
            build(o<<1|1,mid+1,r);
            pushup(o);
        }
        void init(){build(1,1,sze);}
        void add_area(int o,int l,int r,int L,int R,T val){
            if(L<=l&&r<=R){
                lazy[o]+=val;sumv[o]+=(r-l+1)*val;
                return;
            }
            pushdown(o,l,r);
            int mid=l+r>>1;
            if(L<=mid) add_area(o<<1,l,mid,L,R,val);
            if(R>mid)  add_area(o<<1|1,mid+1,r,L,R,val);
            pushup(o);
        }
        T query_area(int o,int l,int r,int L,int R){
            if(L<=l&&r<=R){return sumv[o];}
            pushdown(o,l,r);
            int mid=l+r>>1;
            T ans=0;
            if(L<=mid) ans+=query_area(o<<1,l,mid,L,R);
            if(R>mid)  ans+=query_area(o<<1|1,mid+1,r,L,R);
            pushup(o);
            return ans;
        }
        void add_pos(int o,int l,int r,int pos,T val){
            if(l==r){sumv[o]+=val;return;}
            pushdown(o,l,r);
            int mid=l+r>>1;
            if(pos<=mid) add_pos(o<<1,l,mid,pos,val);
            else       add_pos(o<<1|1,mid+1,r,pos,val);
            pushup(o);
        }
        T query_pos(int o,int l,int r,int pos){
            if(l==r){return sumv[o];}
            pushdown(o,l,r);
            int mid=l+r>>1;
            T ans=0;
            if(pos<=mid) ans=query_pos(o<<1,l,mid,pos);
            else     ans=query_pos(o<<1|1,mid+1,r,pos);
            pushup(o);
            return ans;
        }
        void clear(){
            memset(v,0,sizeof(v));
            memset(sumv,0,sizeof(sumv));
        }
        T get_area(int a,int b){return query_area(1,1,sze,a,b);}
        void up_area(int a,int b,T c){add_area(1,1,sze,a,b,c);}
        T get_pos (int a){return query_pos(1,1,sze,a);}
        void up_pos (int a,T b){add_pos(1,1,sze,a,b);}
        T operator ()(int a,int b){return get_area(a,b);}
        T operator ()(int a){return get_pos(a);}
   };
}
#define ll long long
using namespace Segment_tree;
segment_tree <ll> tr;
int m,cao,x,y;
ll k;
/*Luogu P3372*/
int main()
{
    scanf("%d%d",&tr.sze,&m);
    for(int i=1;i<=tr.sze;i++) scanf("%d",&tr.v[i]);
    tr.init();
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&cao,&x,&y);
        if(cao==1){
            scanf("%lld",&k);
            tr.up_area(x,y,k);
        }else{
            printf("%lld\n",tr(x,y));
        }
    }
    return 0;
}

  • RMQ算法【2018.3.20】
//#include<cstdio>
//#include<cstring>
//#include<algorithm>
//
//using namespace std;
//const int M=1e5+10,Log=17;
//#define MIN
//namespace RMQ{
//#ifdef MIN
//template <class T>
//  T ck(T a,T b){return a<b?a:b;}
//#endif
//#ifndef MIN
//#ifdef MAX
//template <class T>
//  T ck(T a,T b){return a<b?b:a;}
//#endif
//#endif
//template <class T>
//   struct rmq{
//          T rmq[M][Log];
//          int sze;
//          int &size(){return sze;}
//          T &operator [](int a){return rmq[a][0];}
//          void init(){
//              for(int i=1;(1<<i)<=sze;i++){
//                  for(int j=1;j+(1<<i)-1<=sze;j++){
//                      rmq[j][i]=ck(rmq[j][i-1],rmq[j+(1<<(i-1))][i-1]);
//              }
//          }
//      }
//      T query(int l,int r){
//          if(l>r) swap(l,r);
//          int k=0;
//          while(1<<(k+1)<=r-l+1) k++;
//          return ck(rmq[l][k],rmq[r-(1<<k)+1][k]);
//      }
//      T operator ()(int l,int r){return query(l,r);}
//   };
//}
//using namespace RMQ;
//rmq <int> sta;
//int main()
//{
//  scanf("%d",&sta.size());
//  for(int i=1;i<=sta.size();i++){scanf("%d",&sta[i]);}
//  sta.init();
//  int m,l,r;
//  scanf("%d",&m);
//  for(int i=1;i<=m;i++){
//      scanf("%d%d",&l,&r);
//      printf("%d\n",sta(l,r));
//  }
//  return 0;
//}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e5+10,Log=17;
namespace RMQ{
template <class T>
//class==typename
   struct rmq{
        T rmq[M][Log];
        int sze;
        int &size(){return sze;}
        T &operator [](int a){return rmq[a][0];}
        template <typename Comp>
        void init(Comp ck){
            for(int i=1;(1<<i)<=sze;i++){
                for(int j=1;j+(1<<i)-1<=sze;j++){
                    rmq[j][i]=ck(rmq[j][i-1],rmq[j+(1<<(i-1))][i-1]);
                }
            }
        }
        template <typename Comp>
        T query(int l,int r,Comp ck){
            if(l>r) swap(l,r);
            int k=0;
            while(1<<(k+1)<=r-l+1) k++;
            return ck(rmq[l][k],rmq[r-(1<<k)+1][k]);
        }
        template <typename Comp>
        T operator ()(int l,int r,Comp ck){return query(l,r,ck);}
   };
}
using namespace RMQ;
int mi(int a,int b){return a<b?a:b;}
rmq <int> sta;
int main()
{
    scanf("%d",&sta.size());
    for(int i=1;i<=sta.size();i++){scanf("%d",&sta[i]);}
    sta.init(mi);
    int m,l,r;
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&l,&r);
        printf("%d\n",sta(l,r,mi));
    }
    return 0;
}

  • 树链剖分【2018.3.31】
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=1e5+10;
int n,m,root,p;

struct ss{
    int to,last;
    ss(int a=0,int b=0):to(a),last(b){}
}g[M<<1];
int head[M],cnt;
void add(int a,int b){
    g[++cnt]=ss(b,head[a]);head[a]=cnt;
    g[++cnt]=ss(a,head[b]);head[b]=cnt;
}
int dep[M],f[M],son[M],sze[M],num[M],top[M],rf[M],val[M],tim;
void dfs1(int a,int fa,int dp){
    f[a]=fa;dep[a]=dp;sze[a]=1;
    for(int i=head[a];i;i=g[i].last){
        if(g[i].to==fa) continue;
        dfs1(g[i].to,a,dp+1);
        sze[a]+=sze[g[i].to];
        if(!son[a]||sze[g[i].to]>sze[son[a]]) son[a]=g[i].to;
    }
}
void dfs2(int a,int b){
    num[a]=++tim;rf[tim]=a;top[a]=b;
    if(!son[a]) return;
    dfs2(son[a],b);
    for(int i=head[a];i;i=g[i].last){
        if(g[i].to==f[a]||g[i].to==son[a]) continue;
        dfs2(g[i].to,g[i].to);
    }
}

int sumv[M<<2],lazy[M<<2];
void pushup(int o){sumv[o]=(sumv[o<<1]+sumv[o<<1|1])%p;}
int pushdown(int o,int l,int r){
    if(!lazy[o]) return (l+r)>>1;
    lazy[o<<1]+=lazy[o];lazy[o<<1|1]+=lazy[o];
    lazy[o<<1]%=p;lazy[o<<1|1]%=p;
    int mid=l+r>>1;
    sumv[o<<1]+=lazy[o]*(mid-l+1);sumv[o<<1]%=p;
    sumv[o<<1|1]+=lazy[o]*(r-mid);sumv[o<<1|1]%=p;
    lazy[o]=0;
    return mid;
}
void build(int o,int l,int r){
    if(l==r){sumv[o]=val[rf[l]]%p;return;}
    int mid=l+r>>1;
    build(o<<1,l,mid);
    build(o<<1|1,mid+1,r);
    pushup(o);
}
int query(int o,int l,int r,int L,int R){
    if(L<=l&&r<=R) return sumv[o]%p;
    int mid=pushdown(o,l,r),ans=0;
    if(L<=mid) ans=query(o<<1,l,mid,L,R);
    if(R> mid) ans=(ans+query(o<<1|1,mid+1,r,L,R))%p;
    pushup(o);
    return ans;
}
void update(int o,int l,int r,int L,int R,int v){
    if(L<=l&&r<=R){
        sumv[o]=(sumv[o]+v*(r-l+1)%p)%p;
        lazy[o]=(lazy[o]+v)%p;
        return;
    }
    int mid=pushdown(o,l,r);
    if(L<=mid) update(o<<1,l,mid,L,R,v);
    if(R> mid) update(o<<1|1,mid+1,r,L,R,v);
    pushup(o);
}
void add1(int a,int v){update(1,1,tim,num[a],num[a]+sze[a]-1,v);}
int  ask1(int a){return query(1,1,tim,num[a],num[a]+sze[a]-1);}
void add2(int a,int b,int v){
    while(top[a]!=top[b]){
        if(dep[top[a]]<dep[top[b]]) swap(a,b);
        update(1,1,tim,num[top[a]],num[a],v);
        a=f[top[a]];
    }
    if(dep[a]>dep[b]) swap(a,b);
    update(1,1,tim,num[a],num[b],v);
}
int ask2(int a,int b){
    int ans=0;
    while(top[a]!=top[b]){
        if(dep[top[a]]<dep[top[b]]) swap(a,b);
        ans=(ans+query(1,1,tim,num[top[a]],num[a]))%p;
        a=f[top[a]];
    }
    if(dep[a]>dep[b]) swap(a,b);
    return (ans+query(1,1,tim,num[a],num[b]))%p;
}
int cao,a,b,c;
int main()
{
    scanf("%d%d%d%d",&n,&m,&root,&p);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=1;i<n;i++){scanf("%d%d",&a,&b);add(a,b);}
    dfs1(root,0,1);dfs2(root,root);
    build(1,1,tim);
    for(int i=1;i<=m;i++){
        scanf("%d",&cao);
        switch(cao){
            case 1:{
                scanf("%d%d%d",&a,&b,&c);c%=p;
                add2(a,b,c);
                break;
            }
            case 2:{
                scanf("%d%d",&a,&b);
                printf("%d\n",ask2(a,b));
                break;
            }
            case 3:{
                scanf("%d%d",&a,&b);b%=p;
                add1(a,b);
                break;
            }
            case 4:{
                scanf("%d",&a);
                printf("%d\n",ask1(a));
                break;
            }
        }
    }
    return 0;
}

字符串


  • 后缀数组【2018.3.16】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e6+500;
int cnt[M],y[M<<1],sa[M<<1],rak[M<<1],A=256;
char str[M<<1];
int main()
{
    scanf("%s",str);
    int len=strlen(str);
    for(int i=0;i<len;i++) cnt[rak[i]=str[i]]++;
    for(int i=1;i<255;i++) cnt[i]+=cnt[i-1];
    for(int i=len-1;i>=0;i--) sa[--cnt[rak[i]]]=i;
    for(int w=1;w<=len;w<<=1){
        memset(cnt,0,sizeof(cnt));int p=0;
        for(int i=len-w;i<len;i++) y[p++]=i;
        for(int i=0;i<len;i++) if(sa[i]>=w) y[p++]=sa[i]-w;
        for(int i=0;i<len;i++) cnt[rak[y[i]]]++;
        for(int i=1;i<A;i++) cnt[i]+=cnt[i-1];
        for(int i=len-1;i>=0;i--) sa[--cnt[rak[y[i]]]]=y[i];
        swap(y,rak);p=1;
        for(int i=0;i<len;i++){
            if(y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+w]==y[sa[i]+w]) rak[sa[i]]=p-1;
            else rak[sa[i]]=p++;
        }
        if(p>len) break;A=p;
    }
    for(int i=0;i<len;i++){rak[sa[i]]=i;printf("%d ",sa[i]+1);}
    return 0;
}

  • kmp算法【2018.3.29】
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e6+10;
struct kmp{
    bool flag;
    int fail[M];
    char s1[M],s2[M];
    void getfail(char *str,int *f){
        int len=strlen(str);
        f[0]=f[1]=0;
        for(int i=1;i<=len;i++){
            int j=f[i];
            while(j&&str[i]!=str[j])j=f[j];
            if(str[i]==str[j]) f[i+1]=j+1;
            else f[i+1]=0;
        }
    }
    void find(char *a,char *b,int *f){
        int l1=strlen(a),l2=strlen(b);
        getfail(b,f);int j=0;
        for(int i=0;i<l1;i++){
            while(j&&a[i]!=b[j])j=f[j];
            if(a[i]==b[j])j++;
            if(j==l2){printf("%d\n",i-l2+2);}
        }
        if(flag)for(int i=1;i<=l2;i++){printf("%d ",f[i]);}
    }
    void init(){if(!flag)scanf("%*d%*d");scanf("%s%s",s1,s2);}
    void work(){find(s1,s2,fail);}
}K;

int main()
{
    K.flag=1;
    K.init();
    K.work();
    return 0;
}

数论


  • 卢卡斯定理(求组合数&&阶乘取模)【2018.3.16】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e5+10;
ll ny[M],pow[M];//ny为预处理逆元
int n,m,p,T;
ll lucas(int a,int b){
    if(a<b) return 0;
    if(a<p) return pow[a]*ny[b]*ny[a-b]%p;
    return lucas(a/p,b/p)*lucas(a%p,b%p)%p;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&n,&m,&p);
        ny[0]=ny[1]=pow[0]=pow[1]=1ll;
        for(int i=2;i<=n+m;i++) pow[i]=1ll*pow[i-1]*i%p;
        for(int i=2;i<=n+m;i++) ny[i]=1ll*(p-p/i)*ny[p%i]%p;
        for(int i=2;i<=n+m;i++) ny[i]=1ll*ny[i-1]*ny[i]%p;
        printf("%lld\n",lucas(n+m,m));
    }
    return 0;
}

  • 线性基【2018.3.16】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=60;
ll a,p[M];
void insert(ll a){
    for(int i=55;i>=0;i--){
        if(!((a>>i)&1ll)) continue;
        if(!p[i]){p[i]=a;return;}
        a^=p[i];
    }
}
int n;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a);
        insert(a);
    }
    ll ans=0;
    for(int i=55;i>=0;i--){
        ans=max(ans,ans^p[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

  • FFT快速傅里叶变换【2018.3.31】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define db double
#define com Complex

using namespace std;
int n,m;

const int M=3e6+10;
const db  pi=acos(-1);

struct Complex{
    db x,y;
    com(db a=0,db b=0):x(a),y(b){}
    com operator +(com a){return com(x+a.x,y+a.y);}
    com operator -(com a){return com(x-a.x,y-a.y);}
    com operator /(db  a){return com(x/a  ,y/a  );}
    com operator !(     ){return com(x    ,-y   );}
    com operator *(com a){return com(x*a.x-y*a.y,x*a.y+y*a.x);}
}a[M],b[M];
void swap(com &a,com &b){com t=a;a=b;b=t;}

void FFT(com *a,int tot,int f){
    int mid=tot>>1,i,j,k;
    for(i=1,j=mid;i<tot-1;i++){
        if(i<j) swap(a[i],a[j]);
        for(k=mid;j>=k;j-=k,k>>=1);
        if(j<k) j+=k;
    }
    for(i=2;i<=tot;i<<=1){
        mid=i>>1;
        com wn=com(cos(2*pi/i),f*sin(2*pi/i));
        for(j=0;j<tot;j+=i){
            com w=com(1,0),x,y;
            for(k=j;k<j+mid;k++,w=w*wn){
                x=a[k],y=w*a[k+mid];
                a[k]=x+y;a[k+mid]=x-y;
            }
        }
    }
}

void work(){
    int k=1;for(;k<=n+m;k<<=1);
    FFT(a,k,1);FFT(b,k,1);
    for(int i=0;i<=k;i++) a[i]=a[i]*b[i];
    FFT(a,k,-1);
    for(int i=0;i<=n+m;i++)
    printf("%d ",int(a[i].x/k+0.5));
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<=n;i++) scanf("%lf",&a[i].x);
    for(int i=0;i<=m;i++) scanf("%lf",&b[i].x);
    work();
    return 0;
}

计算几何


模板【2018.3.26】 传送门

  • 旋转卡(qia3)壳(ke2) + 凸包 POJ2079 【2018.3.26】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define db double
using namespace std;
const int M=1e5+1;
int n,m;
struct point{
    db x,y;
    point(db a=0,db b=0):x(a),y(b){}
    void in(){scanf("%lf%lf",&x,&y);}
    bool operator <(point a)const{return x<a.x||(x==a.x&&y<a.y);}
}pp[M],ans[M];

point operator -(point a,point b){return point(a.x-b.x,a.y-b.y);}

bool cmp(point a,point b){return (a.y<b.y)||(a.y==b.y&&a.x<b.x);}
db cross(point a,point b){return a.x*b.y-a.y*b.x;}

void convexhull(){
    sort(pp,pp+n);
    m=0;
    for(int i=0;i<n;i++){
        while(m>1&&cross(ans[m-1]-ans[m-2],pp[i]-ans[m-2])<=0) m--;
        ans[m++]=pp[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--){
        while(m>k&&cross(ans[m-1]-ans[m-2],pp[i]-ans[m-2])<=0) m--;
        ans[m++]=pp[i];
    }
    if(n>1)m--;
}

db area(point a,point b,point c){return cross(b-a,c-a);}

db rotcap(){
    db zans=0;
    int p=1,q=2;
    for(int i=0;i<m;i++){
        while(fabs(area(ans[(q+1)%m],ans[i],ans[p]))>fabs(area(ans[q],ans[i],ans[p]))) q=(q+1)%m;
        zans=max(zans,fabs(area(ans[q],ans[i],ans[p])));
        while(fabs(area(ans[(p+1)%m],ans[i],ans[q]))>fabs(area(ans[p],ans[i],ans[q]))) p=(p+1)%m;
        zans=max(zans,fabs(area(ans[p],ans[i],ans[q])));
    }
    return zans/2;
}

int main()
{
    while(scanf("%d",&n)==1&&n>0){
        for(int i=0;i<n;i++) pp[i].in();
        convexhull();
        printf("%.2lf\n",rotcap());
    }
    return 0;
}
1 图论 3 1.1 术语 3 1.2 独立集、覆盖集、支配集之间关系 3 1.3 DFS 4 1.3.1 割顶 6 1.3.2 桥 7 1.3.3 强连通分量 7 1.4 最小点基 7 1.5 拓扑排序 7 1.6 欧拉路 8 1.7 哈密顿路(正确?) 9 1.8 Bellman-ford 9 1.9 差分约束系统(用bellman-ford解) 10 1.10 dag最短路径 10 1.11 二分图匹配 11 1.11.1 匈牙利算法 11 1.11.2 KM算法 12 1.12 网络流 15 1.12.1 最大流 15 1.12.2 上下界的网络的最大流 17 1.12.3 上下界的网络的最小流 17 1.12.4 最小费用最大流 18 1.12.5 上下界的网络的最小费用最小流 21 2 数论 21 2.1 最大公约数gcd 21 2.2 最小公倍数lcm 22 2.3 快速幂取模B^LmodP(O(logb)) 22 2.4 Fermat小定理 22 2.5 Rabin-Miller伪素数测试 22 2.6 Pollard-rho 22 2.7 扩展欧几里德算法extended-gcd 24 2.8 欧拉定理 24 2.9 线性同余方程ax≡b(mod n) 24 2.10 中国剩余定理 25 2.11 Discrete Logging(BL == N (mod P)) 26 2.12 N!最后一个不为0的数字 27 2.13 2^14以内的素数 27 3 数据结构 31 3.1 堆(最小堆) 31 3.1.1 删除最小值元素: 31 3.1.2 插入元素和向上调整: 32 3.1.3 堆的建立 32 3.2 并查集 32 3.3 树状数组 33 3.3.1 LOWBIT 33 3.3.2 修改a[p] 33 3.3.3 前缀和A[1]+…+A[p] 34 3.3.4 一个二维树状数组的程序 34 3.4 线段树 35 3.5 字符串 38 3.5.1 字符串哈希 38 3.5.2 KMP算法 40 4 计算几何 41 4.1 直线交点 41 4.2 判断线段相交 41 4.3 三点外接圆圆心 42 4.4 判断点在多边形内 43 4.5 两圆交面积 43 4.6 最小包围圆 44 4.7 经纬度坐标 46 4.8 凸包 46 5 Problem 48 5.1 RMQ-LCA 48 5.1.1 Range Minimum Query(RMQ) 49 5.1.2 Lowest Common Ancestor (LCA) 53 5.1.3 Reduction from LCA to RMQ 56 5.1.4 From RMQ to LCA 57 5.1.5 An<O(N), O(1)> algorithm for the restricted RMQ 60 5.1.6 An AC programme 61 5.2 最长公共子序列LCS 64 5.3 最长上升子序列/最长不下降子序列(LIS) 65 5.3.1 O(n^2) 65 5.3.2 O(nlogn) 66 5.4 Joseph问题 67 5.5 0/1背包问题 68 6 组合数学相关 69 6.1 The Number of the Same BST 69 6.2 排列生成 71 6.3 逆序 72 6.3.1 归并排序求逆序 72 7 数值分析 72 7.1 二分法 72 7.2 迭代法(x=f(x)) 73 7.3 牛顿迭代 74 7.4 数值积分 74 7.5 高斯消元 75 8 其它 77
1 图论 3 1.1 术语 3 1.2 独立集、覆盖集、支配集之间关系 3 1.3 DFS 4 1.3.1 割顶 6 1.3.2 桥 7 1.3.3 强连通分量 7 1.4 最小点基 7 1.5 拓扑排序 7 1.6 欧拉路 8 1.7 哈密顿路(正确?) 9 1.8 Bellman-ford 9 1.9 差分约束系统(用bellman-ford解) 10 1.10 dag最短路径 10 1.11 二分图匹配 11 1.11.1 匈牙利算法 11 1.11.2 KM算法 12 1.12 网络流 15 1.12.1 最大流 15 1.12.2 上下界的网络的最大流 17 1.12.3 上下界的网络的最小流 17 1.12.4 最小费用最大流 18 1.12.5 上下界的网络的最小费用最小流 21 2 数论 21 2.1 最大公约数gcd 21 2.2 最小公倍数lcm 22 2.3 快速幂取模B^LmodP(O(logb)) 22 2.4 Fermat小定理 22 2.5 Rabin-Miller伪素数测试 22 2.6 Pollard-rho 22 2.7 扩展欧几里德算法extended-gcd 24 2.8 欧拉定理 24 2.9 线性同余方程ax≡b(mod n) 24 2.10 中国剩余定理 25 2.11 Discrete Logging(BL == N (mod P)) 26 2.12 N!最后一个不为0的数字 27 2.13 2^14以内的素数 27 3 数据结构 31 3.1 堆(最小堆) 31 3.1.1 删除最小值元素: 31 3.1.2 插入元素和向上调整: 32 3.1.3 堆的建立 32 3.2 并查集 32 3.3 树状数组 33 3.3.1 LOWBIT 33 3.3.2 修改a[p] 33 3.3.3 前缀和A[1]+…+A[p] 34 3.3.4 一个二维树状数组的程序 34 3.4 线段树 35 3.5 字符串 38 3.5.1 字符串哈希 38 3.5.2 KMP算法 40 4 计算几何 41 4.1 直线交点 41 4.2 判断线段相交 41 4.3 三点外接圆圆心 42 4.4 判断点在多边形内 43 4.5 两圆交面积 43 4.6 最小包围圆 44 4.7 经纬度坐标 46 4.8 凸包 46 5 Problem 48 5.1 RMQ-LCA 48 5.1.1 Range Minimum Query(RMQ) 49 5.1.2 Lowest Common Ancestor (LCA) 53 5.1.3 Reduction from LCA to RMQ 56 5.1.4 From RMQ to LCA 57 5.1.5 An algorithm for the restricted RMQ 60 5.1.6 An AC programme 61 5.2 最长公共子序列LCS 64 5.3 最长上升子序列/最长不下降子序列(LIS) 65 5.3.1 O(n^2) 65 5.3.2 O(nlogn) 66 5.4 Joseph问题 67 5.5 0/1背包问题 68 6 组合数学相关 69 6.1 The Number of the Same BST 69 6.2 排列生成 71 6.3 逆序 72 6.3.1 归并排序求逆序 72 7 数值分析 72 7.1 二分法 72 7.2 迭代法(x=f(x)) 73 7.3 牛顿迭代 74 7.4 数值积分 74 7.5 高斯消元 75 8 其它 77
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VictoryCzt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值