零、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
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分治例题//题解