ACM算法blog与模板合集(逐步完善中)

零、OI-WIKI

https://oi-wiki.org/

一、数据结构

1.LCA&&树链剖分:

LCA是用来求最近公共祖先的算法
树链剖分可以快速求出树上两点之间的信息
https://blog.csdn.net/enjoy_pascal/article/details/78277008

2.树上启发式合并(dsu on tree):

可以统计各个结点为根的子树的信息
https://blog.csdn.net/qq_40791842/article/details/90731159

3.点分治&&动态点分治:

统计所有边的信息

https://www.cnblogs.com/bztMinamoto/p/9489473.html
题集:
POJ1741
洛谷3806
BZOJ2152
洛谷4149
洛谷2664

4.主席树:

https://blog.csdn.net/creatorx/article/details/75446472

5.带权并查集:

带权并查集处理的是多个关系存在时是否有关系存在矛盾的问题
https://blog.csdn.net/sunmaoxiang/article/details/80959300

二、图论

1.线段树优化建边:

https://blog.csdn.net/yjt9299/article/details/81301334

2.带上下界的网络流:

https://www.cnblogs.com/liu-runda/p/6262832.html

3.差分约束问题:

https://blog.csdn.net/dragon60066/article/details/80245797

4.有向图的强连通与2-sat问题

https://blog.csdn.net/WhereIsHeroFrom/article/details/79417926
https://blog.csdn.net/jarjingx/article/details/8521690

三、数论

1.欧拉定理&&费马小定理:

https://blog.csdn.net/jinli_/article/details/88771852

2.原根:

https://blog.csdn.net/ACdreamers/article/details/8883285
(在模p的情况下,原根rt可以用来表示(1~p-1)的数——{rt ^ 1,rt ^ 2…,rt ^ (p-1)}
例如5的原根为2
1=2^4%5;
2=2^1%5;
3=2^3%5;
4=2^2%5;
(由于原根一般不大,可以暴力求解:从2开始枚举,然后暴力判断g^φ( P ) = 1 (mod P)是否当且当阶为φ( P )的时候成立

bool check(int g) {
    int tp = 1;
    for (int i = 1; i < P - 1; ++i) {
        tp = 1ll * tp * g % P;
        if (tp == 1) return 0;
    }
    return true;
}
void get() {
    int g = 2;
    for (int i = 2; ; ++i) if (check(i)) {
        g = i;
        break;
    }
}

3.逆元:

https://blog.csdn.net/qq_40861916/article/details/82928080

4.单纯形:

单纯形法解决的是线性规划的问题
https://www.hrwhisper.me/introduction-to-simplex-algorithm/#comments
*这里是蔡队的板子,用这个板子需要注意的是a [m] 数组放置的是目标函数的系数,并且a[m] [n] 放置的是目标函数的值(a[i][n]放置的都是标准式右边的值)
这个板子也不需要填入松弛后产生的xi的系数

const int maxm = 500; // 约束数目上限
const int maxn = 500; // 变量数目上限
const double INF = 1e100;
const double eps = 1e-10;
double x[maxm];
struct Simplex
{
    int n;                // 变量个数
    int m;                // 约束个数
    double a[maxm][maxn]; // 输入矩阵
    int B[maxm], N[maxn]; // 算法辅助变量
    void pivot(int r, int c)
    {
        swap(N[c], B[r]);
        a[r][c] = 1 / a[r][c];
        for (int j = 0; j <= n; j++)
            if (j != c) a[r][j] *= a[r][c];
        for (int i = 0; i <= m; i++)
            if (i != r)
            {
                for (int j = 0; j <= n; j++)
                    if (j != c) a[i][j] -= a[i][c] * a[r][j];
                a[i][c] = -a[i][c] * a[r][c];
            }
    }
    bool feasible()
    {
        for (;;)
        {
            int r, c;
            double p = INF;
            for (int i = 0; i < m; i++)
                if (a[i][n] < p) p = a[r = i][n];
            if (p > -eps) return true;
            p = 0;
            for (int i = 0; i < n; i++)
                if (a[r][i] < p) p = a[r][c = i];
            if (p > -eps) return false;
            p = a[r][n] / a[r][c];
            for (int i = r + 1; i < m; i++)
                if (a[i][c] > eps)
                {
                    double v = a[i][n] / a[i][c];
                    if (v < p) r = i, p = v;
                }
            pivot(r, c);
        }
    }
    // 解有界返回1,无解返回0,无界返回-1。b[i]为x[i]的值,ret为目标函数的值
    int simplex(int n, int m, double x[maxn], double& ret)
    {
        this->n = n, this->m = m;
        for (int i = 0; i < n; i++) N[i] = i;
        for (int i = 0; i < m; i++) B[i] = n + i;
        if (!feasible()) return 0;
        for (;;)
        {
            int r, c;
            double p = 0;
            for (int i = 0; i < n; i++)
                if (a[m][i] > p) p = a[m][c = i];
            if (p < eps)
            {
                for (int i = 0; i < n; i++)
                    if (N[i] < n) x[N[i]] = 0;
                for (int i = 0; i < m; i++)
                    if (B[i] < n) x[B[i]] = a[i][n];
                ret = -a[m][n];
                return 1;
            }
            p = INF;
            for (int i = 0; i < m; i++)
                if (a[i][c] > eps)
                {
                    double v = a[i][n] / a[i][c];
                    if (v < p) r = i, p = v;
                }
            if (p == INF) return -1;
            pivot(r, c);
        }
    }
};

那么,如何求目标函数的最小值呢
假如z=x1+x2,求z的最小值
那么我们只需要两边乘-1得到-z=-x1-x2
另z1=-z,然后求z1的最大值即可

5.高斯消元:

高斯消元可以解方程组
https://blog.csdn.net/pengwill97/article/details/77200372
(异或高斯消元模板

#include<bits/stdc++.h>
using namespace std;
#define MAX_SIZE 350
#define ll long long
ll Matrix[MAX_SIZE][MAX_SIZE];
ll Free_x[MAX_SIZE];   //自由变元
ll X_Ans[MAX_SIZE];  //解集 
ll Free_num=0;  //自由变元数
 
ll Guass(ll Row,ll Column)  //系数矩阵的行和列
{
    ll row=0,col=0,max_r;
    for(row=0;row<Row&&col<Column;row++,col++)
    {
        max_r=row;
        for(ll i=row+1;i<Row;i++)   //找出当前列最大值
            if(abs(Matrix[i][col])>abs(Matrix[max_r][col]))
                max_r=i;
        if(Matrix[max_r][col]==0)  //记录自由变元
        {
            row--;
            Free_x[Free_num++]=col+1;
            continue;
        }
        if(max_r!=row)  //交换
            for(ll i=col;i<Column+1;i++)
                swap(Matrix[row][i],Matrix[max_r][i]);
        for(ll i=row+1;i<Row;i++)   //消元
        {
            if(Matrix[i][col]!=0)
            {
                for(ll j=col;j<Column+1;j++)
                    Matrix[i][j]^=Matrix[row][j];
            }
        }
    }
    for(ll i=row;i<Row;i++)   //无解
        if(Matrix[i][Column]!=0)
            return -1;
 
    if(row<Column)   //无穷多解
        return Column-row;
    
    //唯一解
    for(ll i=Column-1;i>=0;i--)
    {
        X_Ans[i]=Matrix[i][Column];
        for(ll j=i+1;j<Column;j++)
           X_Ans[i]^=(Matrix[i][j]&&X_Ans[j]);
    }
    return 0;
}

6.矩阵快速幂:

https://blog.csdn.net/wust_zzwh/article/details/52058209

7.线性基:

https://blog.csdn.net/Anxdada/article/details/80088007?tdsourcetag=s_pcqq_aiomsg

8.二次剩余

https://blog.csdn.net/kele52he/article/details/78897187
http://blog.miskcoo.com/2014/08/quadratic-residue

9.FFT&&NNT //不是会抄个板子就行了吗(雾

https://blog.csdn.net/enjoy_pascal/article/details/81478582
https://blog.csdn.net/enjoy_pascal/article/details/81771910

10.FWT

https://www.cnblogs.com/cjyyb/p/9065615.html

四、动态规划

1.最长公共上升子序列:

https://www.cnblogs.com/WArobot/p/7479431.html

2.斜率优化dp:

https://www.luogu.org/problemnew/solution/P3195
2019牛客多校第十场J题

3.数位dp:

https://blog.csdn.net/wust_zzwh/article/details/52100392
2019牛客多校第七场H题

4.最大字段和

https://www.cnblogs.com/TIMHY/p/8284989.html

五、字符串

1.字符串hash

https://blog.csdn.net/pengwill97/article/details/80879387

hdu4622 //题解

2.最长回文子串——Manacher:

https://blog.csdn.net/WhereIsHeroFrom/article/details/79719507

3.单模板匹配算法——KMP:

https://blog.csdn.net/v_july_v/article/details/7041827

4.拓展kmp

https://blog.csdn.net/dyx404514/article/details/41831947

5.多模板匹配算法——AC自动机:

https://blog.csdn.net/creatorx/article/details/71100840

6.回文树(PTM):

https://blog.csdn.net/u013368721/article/details/42100363
题目:
浙大宁波理工学院C题

7.后缀数组(SA):

https://www.cnblogs.com/victorique/p/8480093.html#autoid-1-3-2
https://www.cnblogs.com/jinkun113/p/4743694.html
题集:
kuangbin
plus

8.后缀自动机(SAM):

http://hihocoder.com/problemset //在里面搜索后缀自动机
https://blog.csdn.net/qq_35649707/article/details/66473069

六、几何

1.凸包问题:

https://blog.csdn.net/Bone_ACE/article/details/46239187
Graham扫描法模板

const double eps=1e-8;
 
int sgn(double x)
{
    if(fabs(x)<eps)
        return 0;
    if(x<0)
        return -1;
    else
        return 1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x-b.x,y-b.y);
    }
    double operator ^(const Point &b)const
    {
        return x*b.y-y*b.x;
    }
    double operator *(const Point &b)const
    {
        return x*b.x+y*b.y;
    }
};

Point p[maxn];
int n;
int Stack[maxn];
int top;
 
double dist(Point a,Point b)
{
    return sqrt((a-b)*(a-b));
}
bool cmp(Point a,Point b)
{
    int ans=sgn((a-p[0])^(b-p[0]));
    if(ans==1)
        return true;
    else if(ans==0)
        return dist(a,p[0])<dist(b,p[0]);
    else
        return false;
}
 
void graham()
{
    for(int i=0;i<n;i++)
    {
        if(p[i].x<p[0].x||(p[i].x==p[0].x&&p[i].y<p[0].y))
            swap(p[0],p[i]);
    }
    sort(p+1,p+n,cmp);
    if(n==1)
    {
        Stack[0]=0;
        top=1;
    }
    else if(n==2)
    {
        Stack[0]=0;
        Stack[1]=1;
        top=2;
    }
    else
    {
        Stack[0]=0;
        Stack[1]=1;
        top=2;
        for(int i=2;i<n;i++)
        {
            while(top>1&&sgn((p[Stack[top-1]]-p[Stack[top-2]])^(p[i]-p[Stack[top-2]]))<=0)
                top--;
            Stack[top++]=i;
        }
    }
}

七、优雅的暴力

1.分块算法:

http://hzwer.com/8053.html

2.莫队算法:

https://www.cnblogs.com/WAMonster/p/10118934.html

八、分治

1.CDQ分治与整体二分

https://www.luogu.org/blog/Owencodeisking/post-xue-xi-bi-ji-cdq-fen-zhi-hu-zheng-ti-er-fen
三维CDQ分治例题//题解

九、刷题指南

BZOJ
Kuangbin
POJ

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值