Hello

#include <iostream>
#include <cstdio>
#include <cctype>
#include <cmath>
#include <cstring>
#include <string>
#include <vector>
#include <algorithm>
#include <queue>
#include <stack> using namespace std;
typedef long long ll; int main() {
cout << "Hello world!" << endl;
return 0;
}

标准库

<algorithm>

__gcd(a, b)				// 求两个数的最大公因数
__builtin_popcount(a) // 求 int 的二进制里多少个 1 is_sorted(a, a + n) // 是否升序
is_sorted_until(a, a + n) // 到哪里是升序
sort(a, a + n) // 不稳定排序(默认升序)
sort(a, a + n, greater<int>()) // 降序排序
stable_sort(a, a + n) // 稳定排序
nth_element(a, a + k, a + n) // 将第 k 大元素放到 a[k]
unique(begin, end) // 对有序数组去重,返回末尾地址 max(a, b) // 返回较大值
min(a, b) // 返回较小值
max_element(a, a + n) // 返回最大值位置
min_element(a, a + n) // 返回最小值位置 lower_bound(a, a + n, key) // 返回第一个不小于 key 的元素的位置
upper_bound(a, a + n, key) // 返回第一个大于 key 的元素的位置
binary_search(a, a + n, key) // 二分查找是否存在 is_heap(a, a + n) // 判断是否为大顶堆
is_heap_until(a, a + n) // 到哪里是大顶堆
make_heap(a, a + n) // 区间建堆
push_heap(a, a + n) // 末尾元素入堆并调整,与 push_back() 配合
pop_heap(a, a + n) // 堆顶移到末尾并调整,与 pop_back() 配合
sort_heap(a, a + n) // 升序堆排序 is_permutation() // 两个序列是否互为另一个的排序
next_permutation() // 下一个排序
prev_permutation() // 上一个排序 fill(a, a + n, val) // 批量赋值
reverse(a, a + n) // 数组翻转

<vector>

v.at(k)					// 访问 v[k]
v.front() // 首元素
v.back() // 末元素
v.begin() // 首地址(迭代器)
v.end() // 末地址(迭代器)
v.empty() // 是否空
v.size() // 大小
v.max_size() // 最大空间
v.clear() // 清除
v.insert(pos, item) // 在 pos(迭代器) 位置插入 item
v.eraze(pos) // 擦除 pos(迭代器) 位置的元素
v.push_back(item) // 末尾插入
v.pop_back() // 末尾删除

<queue>

/*----- queue -----*/
q.front() // 访问队头
q.back() // 访问队尾
q.empty() // 是否空
q.size() // 大小
q.push(item) // item 入队
q.emplace(item) // item 替换队尾
q.pop() // 出队
/*----- priority_queue -----*/
priority_queue<int, vector<int>, greater<int>> pq
pq.top() // 访问队首
pq.empty() // 优先队列是否空
pq.size() // 大小
pq.push(item) // 插入 item
pq.pop() // 出队

<stack>

s.top()					// 访问栈顶
s.empty() // 栈是否空
s.size() // 大小
s.push(item) // item 入栈
s.emplace(item) // item 替换栈顶
s.pop() // 出栈

<set>

/*----- set -----*/
s.size() // 大小
s.empty() // 是否空
s.clear() // 清除
s.insert(key) // 插入
s.erase(pos/key) // 删除
s.count(key) // 是否存在
s.find(key) // 查找,成功返回位置,失败返回 s.end()
/*----- multiset -----*/
ms.size() // 大小
ms.empty() // 是否空
ms.clear() // 清除
ms.insert(key) // 插入
ms.erase(pos/key) // 删除
ms.count(key) // 计数
ms.find(key) // 查找,成功返回位置,失败返回 s.end()

<map>

/*----- map -----*/
/*----- mulmap -----*/

<unordered_set>

/*----- unordered_set -----*/
/*----- unordered_multiset -----*/

<unordered_map>

/*----- unordered_map -----*/
/*----- unordered_multimap -----*/

分治

逆序对计数

#include <iostream>

using namespace std;
typedef long long ll; int temp[200005]; ll solve(int a[], int left, int right); int main() {
int n;
int a[200005] = {};
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
cout << solve(a, 0, n - 1);
return 0;
}
ll solve(int a[], int left, int right) {
if (left == right)
return 0;
else {
int mid = (right - left) / 2 + left;
ll s1 = solve(a, left, mid);
ll s2 = solve(a, mid + 1, right);
ll s3 = 0;
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) {
if (a[i] <= a[j]) {
temp[left + k] = a[i];
k++;
i++;
} else {
temp[left + k] = a[j];
s3 += (mid - i + 1);
k++;
j++;
}
}
if (i <= mid)
while (i <= mid) {
temp[k + left] = a[i];
k++;
i++;
}
else
while (j <= right) {
temp[k + left] = a[j];
k++;
j++;
}
for (int l = left; l <= right; l++)
a[l] = temp[l];
return s1 + s2 + s3;
}
}

动态规划

01 背包

#include <iostream>
#include <algorithm> #define ll long long
#define MAX_NUM 1005 //物品数量
#define MAX_CAP 100005 //最大容量
using namespace std; ll dp[MAX_CAP];
int v[MAX_NUM];
int w[MAX_NUM]; ll backBag(ll Bag[], int *value, int *weight, int num, int cap) {
// dp数组,价值,重量,容量
for(int i = 0; i <= cap; i++)
Bag[i] = 0;
for (int i = 1; i <= num; i++)
for (int j = cap; j >= weight[i]; j--) //倒着dp
Bag[j] = max(Bag[j - weight[i]] + value[i], Bag[j]);
return Bag[cap];
} int main() {
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> v[i] >> w[i];
cout << backBag(dp, v, w, n, k);
return 0;
}

完全背包

#include <iostream>
#include <algorithm> #define ll long long
#define MAX_NUM 10005 //物品数量
#define MAX_CAP 10000005 //最大容量
using namespace std; ll dp[MAX_CAP];
int v[MAX_NUM];
int w[MAX_NUM]; ll backBag(ll Bag[], int *value, int *weight, int num, int cap) {
// dp数组,价值,重量,容量
for(int i = 0; i <= cap; i++)
Bag[i] = 0;
for (int i = 1; i <= num; i++)
for (int j = weight[i]; j <= cap; j++) //正着dp
Bag[j] = max(Bag[j - weight[i]] + value[i], Bag[j]);
return Bag[cap];
} int main() {
int n, k;
cin >> k >> n;
for (int i = 1; i <= n; i++)
cin >> w[i] >> v[i];
cout << backBag(dp, v, w, n, k);
return 0;
}

分组背包

#include <iostream>
#include <algorithm> typedef long long ll; const int MAX = 1005; struct {
int cnt;
ll ID[MAX];
} group[MAX]; //用一个结构体来存储每一组的物品编号 ll dp[MAX];
ll val[MAX];
ll weight[MAX]; ll group_bag(int cap, int max_group); using namespace std; int main() {
// freopen("a.in", "r", stdin);
// freopen("a.out", "w", stdout);
int n, m;
cin >> m >> n;
int a, b, k, max_group = 0;
for (int i = 1; i <= n; i++) {
cin >> a >> b >> k;
weight[i] = a;
val[i] = b;
group[k].ID[group[k].cnt++] = i;
max_group = max(max_group, k);
}
cout << group_bag(m, max_group);
return 0;
} ll group_bag(int cap, int max_group) {
for (int i = 0; i <= max_group; i++) // 第一层组循环
for (ll j = cap; j >= 0; j--) // 第二层容量倒着循环
for (int k = 0; k < group[i].cnt; k++) // 第三层组内循环
if (j >= weight[group[i].ID[k]])
dp[j] = max(dp[j],
dp[j - weight[group[i].ID[k]]] + val[group[i].ID[k]]);
return dp[cap];
}

最大子列和

#include <iostream>
#include <algorithm> #define MAX 1000005
#define ll long long
using namespace std; int a[MAX]; ll maxSubArray(int *array, int n) {
ll Max = -0x3f3f3f3f3f3f3f3f;
ll sum = 0;
for (int i = n - 1; i >= 0; i--) {
if (sum <= 0)
sum = array[i];
else
sum += array[i];
Max = max(sum, Max);
}
return Max;
} int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
cout << maxSubArray(a, n);
return 0;
}

LCS 最长公共子序列

#include <iostream>
#include <string>
#define MAX 1005
using namespace std; struct Tab{
int x, y;
} trac[MAX][MAX]; int lcs[MAX][MAX]; void print_lcs(string str, int i, int j); int main() {
int k;
cin >> k;
string sa, sb;
cin >> sa >> sb;
int la = (int)sa.length();
int lb = (int)sb.length();
for (int i = 1; i <= la; i++) {
for (int j = 1; j <= lb; j++) {
if (sa[i - 1] == sb[j - 1]) {
lcs[i][j] = lcs[i - 1][j - 1] + 1;
trac[i][j] = {i - 1, j - 1};
} else if (lcs[i - 1][j] >= lcs[i][j - 1]) {
lcs[i][j] = lcs[i - 1][j];
trac[i][j] = {i - 1, j};
} else {
lcs[i][j] = lcs[i][j - 1];
trac[i][j] = {i, j - 1};
}
}
}
if(k == 0)
cout << lcs[la][lb];
else
print_lcs(sa, la, lb);
return 0;
} void print_lcs(string str, int i, int j){
if(i == 0 || j == 0)
return ;
if(trac[i][j].x == i - 1 && trac[i][j].y == j - 1){
print_lcs(str, i - 1, j - 1);
cout << str[i - 1];
}else if(trac[i][j].x == i - 1 && trac[i][j].y == j)
print_lcs(str, i - 1, j);
else
print_lcs(str, i, j - 1);
}

最小编辑距离

#include <iostream>
#include <string>
#define MAX 2005
using namespace std; int min3(int a, int b, int c) {
int m = a;
if (b < m)
m = b;
if (c < m)
return c;
return m;
}
int minDistance(string word1, string word2) {
int dp[2][MAX] = {};
int l1 = word1.length();
int l2 = word2.length();
for (int j = 0; j <= l2; j++)
dp[0][j] = j;
for (int i = 1; i <= l1; i++) {
dp[1][0] = i;
for (int j = 1; j <= l2; j++)
if (word1[i - 1] == word2[j - 1])
dp[1][j] = dp[0][j - 1];
else
dp[1][j] = min3(dp[0][j - 1], dp[0][j], dp[1][j - 1]) + 1;
for (int j = 0; j <= l2; j++)
dp[0][j] = dp[1][j];
}
return dp[0][l2];
}
int main() {
string a;
string b;
cin >> a >> b;
cout << minDistance(a, b);
return 0;
}

最长单调子序列

// 严格单调递增子列的长度
int lsrsa(const vector<int> &a) {
vector<int> sa;
for (auto x: a) {
if (sa.empty() || x > sa.back())
sa.push_back(x);
else
*lower_bound(sa.begin(), sa.end(), x) = x;
}
return (int) sa.size();
}
// 单调不减子列的长度
int lrsa(const vector<int> &a) {
vector<int> sa;
for (auto x: a) {
if (sa.empty() || x >= sa.back())
sa.push_back(x);
else
*upper_bound(sa.begin(), sa.end(), x) = x;
}
return (int) sa.size();
}

图算法

链式前向星

struct Edge{
int to, w, next; //终点,权值,前驱
} e[E_MAX]; int cnt_E = 0;
int head[V_MAX]; //需要先初始化为-1 void intList(int n){
memset(head, -1, sizeof(head));
} void addEdge(int x, int y, int w){
e[cnt_E].to = y; //保存终点
e[cnt_E].next = head[x]; //添加链接
head[x] = cnt++; //更新表头
}

Dijkstra 最短路(标准版)

#include <iostream>
#include <vector>
#include <cstring> #define V_MAX 100005
#define INF 0x3f3f3f3f3f3f3f3f using namespace std;
typedef long long ll; struct Edge {
int to;
ll weight;
}; vector<Edge> e[V_MAX];
ll dis[V_MAX];
bool vis[V_MAX];
int n, m; void addEdge(int u, int v, ll w);
void dijkstra(int s); int main() {
int s;
cin >> n >> m >> s;
int x, y;
ll w;
for (int i = 0; i < m; ++i) {
cin >> x >> y >> w;
addEdge(x, y, w);
}
dijkstra(s);
// 最短路保存在 dis 中
for (int i = 1; i <= n; i++) {
if (dis[i] == INF)
cout << -1 << " ";
else
cout << dis[i] << " ";
}
return 0;
} void addEdge(int u, int v, ll w) {
e[u].push_back({v, w});
} void dijkstra(int s) {
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
for (int i = 1; i <= n; i++) {
int u = 0;
ll mind = INF;
for (int j = 1; j <= n; j++)
if (!vis[j] && dis[j] < mind) {
u = j;
mind = dis[j];
}
vis[u] = true;
for (auto ed: e[u]) {
int v = ed.to;
ll w = ed.weight;
if (dis[v] > dis[u] + w)
dis[v] = dis[u] + w;
}
}
}

Dijkstra 最短路(堆优化)

#include <iostream>
#include <algorithm>
#include <queue>
#include <vector> #define V_MAX 100005
#define INF 0x3f3f3f3f3f3f3f3f using namespace std; typedef long long ll; struct Edge {
int to;
ll w;
}; struct Node {
ll dis;
int u;
bool operator>(const Node &b) const {return dis > b.dis; }
}; vector<Edge> e[V_MAX]; void addEdge(int u, int v, ll w) {
e[u].push_back({v, w});
} vector<ll> dijkstra(int s) {
priority_queue<Node, vector<Node>, greater<Node>> q;
vector<ll> dis(V_MAX);
fill(dis.begin(), dis.end(), INF);
vector<bool> vis(V_MAX);
dis[s] = 0;
q.push({0, s});
while (!q.empty()){
int u = q.top().u;
q.pop();
if(vis[u])continue;
vis[u] = true;
for (auto ed : e[u]){
int v = ed.to;
ll w = ed.w;
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
return dis;
} int main() {
int n, m;
int s;
cin >> n >> m >> s;
int x, y, w;
for (int i = 0; i < m; i++) {
cin >> x >> y >> w;
addEdge(x, y, w);
}
vector<ll> dis = dijkstra(s);
for (int i = 1; i <= n; i++) {
cout << dis[i] << " ";
}
return 0;
}

Floyd 最短路

#include <algorithm>
#include <cstring>
#include <iostream> #define V_MAX 510 // 结点数
#define INF 0x3f3f3f3f3f3f3f3f using namespace std;
typedef long long ll; ll f[V_MAX][V_MAX]; // 邻接矩阵存图 int main() {
int n, m, p;
ll x, y, w;
cin >> n >> m >> p;
for (x = 1; x <= n; x++)
for (y = 1; y <= n; y++)
f[x][y] = INF;
for (int i = 1; i <= n; i++)
f[i][i] = 0; /*-----初始化部分-----*/ for (int i = 0; i < m; i++) {
cin >> x >> y >> w;
if (w < f[x][y]) // 考虑重边的情况
f[x][y] = w;
} /*-----读入-----*/ for (int k = 1; k <= n; k++)
for (x = 1; x <= n; x++)
for (y = 1; y <= n; y++)
f[x][y] = min(f[x][y], f[x][k] + f[k][y]); /*----- Floyd -----*/ for (int i = 0; i < p; i++) {
cin >> x >> y;
if (f[x][y] != INF)
cout << f[x][y] << endl;
else
cout << "-1" << endl;
} /*-----输出-----*/
return 0;
}

Kruskal 最小生成树

#include <algorithm>
#include <iostream> #define V_MAX 300005
#define E_MAX 500005 using namespace std;
typedef long long ll; struct Edge {
int x, y, w;
bool operator<(const Edge &b) const { return w < b.w; }
} e[E_MAX]; int v[V_MAX]; int Find(int x);
bool isUnion(int x, int y);
void Union(int x, int y); //合并
void makeSet(int n); //初始化并查集 int main() {
int n, m;
cin >> n >> m;
makeSet(n);
for (int i = 0; i < m; i++)
cin >> e[i].x >> e[i].y >> e[i].w;
sort(e, e + m);
int cnt = 0;
ll sum = 0;
for(int i = 0; cnt < n - 1; i++){
if(isUnion(e[i].x, e[i].y))
continue;
cnt++;
sum += e[i].w;
Union(e[i].x, e[i].y);
}
cout << sum;
return 0;
} void makeSet(int n) {
for (int i = 1; i <= n; i++)
v[i] = i;
} int Find(int x) {
if (v[x] == x)
return x;
return v[x] = Find(v[x]);
} bool isUnion(int x, int y) { return Find(x) == Find(y); }
void Union(int x, int y) { v[Find(y)] = Find(x); }

Kahn 拓扑排序

#include <cstring>
#include <iostream>
#include <queue>
#include <vector> #define E_MAX 400005
#define V_MAX 100005 using namespace std; struct Edge { //链式前向星,存边的起点、终点、和前驱
int x, y, next;
} e[E_MAX]; int head[V_MAX]; //下标是起点的表头,存第一个边的编号,初始化为 -1
int id[V_MAX]; //每个点的入度
int cnt; //存储的边数 void addEdge(int x, int y);
bool Kahn(int n); int main() {
int n, m, x, y;
cin >> n >> m; fill(head + 1, head + 1 + n, -1); /*----- 初始化 -----*/ for (int i = 0; i < m; i++) {
cin >> x >> y;
addEdge(x, y);
} /*----- 读入边 -----*/ Kahn(n);
return 0;
}
void addEdge(int x, int y) {
e[cnt].x = x; //起点
e[cnt].y = y; //终点
e[cnt].next = head[x]; //添加
id[y]++;
head[x] = cnt++; //更新表头
}
bool Kahn(int n) {
priority_queue<int> q; //优先队列
for (int i = 1; i <= n; i++) {
if (id[i] == 0)
q.push(i); //把入度为0的点入队
}
vector<int> ans; //数组保存结果
while (!q.empty()) {
int x = q.top(); //出队
q.pop();
ans.push_back(x);
int edge = head[x];
while (edge != -1) {
id[e[edge].y]--; //删除边
if (id[e[edge].y] == 0)
q.push(e[edge].y);
edge = e[edge].next;
}
}
if (ans.size() == n) {
for (int an : ans)
cout << an << " ";
return true;
} /*----- 无环则输出并返回真 -----*/ return false;
}

Dinic 最大流

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
const int V_MAX = 205;
const int E_MAX = 5005;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f; ll max_stream = 0;
int cnt_E = 0;
int n, m, s, t; struct Edge {
int to;
int nxt;
ll val;
} e[E_MAX * 2]; int head[V_MAX];
int depth[V_MAX]; void addEdge(int x, int y, int w);
void read();
bool bfs();
ll Dinic(); int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> s >> t; fill(head + 1, head + 1 + n, -1); /*----- 读入并初始化 -----*/ read();
cout << Dinic();
return 0;
}
void addEdge(int x, int y, int w) {
e[cnt_E].to = y;
e[cnt_E].val = w;
e[cnt_E].nxt = head[x];
head[x] = cnt_E++;
}
void read() {
int u, v, w;
for (int i = 0; i < m; i++) {
cin >> u >> v >> w;
addEdge(u, v, w);
addEdge(v, u, 0);
}
}
bool bfs() {
memset(depth, 0, sizeof(depth));
depth[s] = 1;
queue<int> q;
q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; i > -1; i = e[i].nxt) {
int v = e[i].to;
if (e[i].val && !depth[v]) {
depth[v] = depth[u] + 1;
q.push(v);
}
}
}
if (depth[t] != 0)
return true;
return false;
} ll dfs(int pos, ll in) {
if (pos == t)
return in;
ll out = 0;
for (int u = head[pos]; u > -1 && in; u = e[u].nxt) {
int v = e[u].to;
if (e[u].val && depth[v] == depth[pos] + 1) {
ll res = dfs(v, min(e[u].val, in));
e[u].val -= res;
e[u ^ 1].val += res;
in -= res;
out += res;
}
}
if (out == 0)
depth[pos] = 0;
return out;
}
ll Dinic() {
while (bfs())
max_stream += dfs(s, LL_INF);
return max_stream;
}

二分图匹配

#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath> using namespace std; struct pos {
int x, y;
}; vector<pos> left;
vector<pos> right; struct augment_path {
// 结点编号从 0 开始
vector<vector<int>> g;
vector<int> pa;
vector<int> pb;
vector<int> vis;
int n, m;
int dfn;
int res; augment_path(int _n, int _m) : n(_n), m(_m) {
pa = vector<int>(n, -1);
pb = vector<int>(m, -1);
vis = vector<int>(n);
g.resize(n);
res = dfn = 0;
} void add(int from, int to) {
g[from].push_back(to);
} bool dfs(int v) {
vis[v] = dfn;
for (int u: g[v])
if (pb[u] == -1) {
pb[u] = v;
pa[v] = u;
return true;
}
for (int u: g[v])
if (vis[pb[u]] != dfn && dfs(pb[u])) {
pa[v] = u;
pb[u] = v;
return true;
}
return false;
} int solve() {
while (true) {
dfn++;
int cnt = 0;
for (int i = 0; i < n; i++)
if (pa[i] == -1 && dfs(i))
cnt++;
if (cnt == 0)
break;
res += cnt;
}
return res;
}
}; int main() {
int n, m, e;
cin >> n >> m >> e;
augment_path solver(n, m);
int u, v;
for(int i = 0; i < e; i++){
cin >> u >> v;
solver.add(u - 1, v - 1);
}
cout << solver.solve() << endl;
return 0;
}

计算几何

线段相交计数

#include <iostream>
#include <algorithm>
#include <vector> using namespace std; struct Point {
int x, y; Point operator+(const Point &b) const {
return {x + b.x, y + b.y};
} Point operator-(const Point &b) const {
return {x - b.x, y - b.y};
} Point operator*(const int &b) const {
return {x * b, y * b};
} int operator^(const Point &b) const {
return x * b.y - y * b.x;
}
}; struct Line {
Point p;
Point q;
}; vector<Line> lines; bool intersect(Line l1, Line l2); bool onSegment(Point point, Line line); int main() {
int n, cnt = 0;
cin >> n;
int x1, y1, x2, y2;
for (int i = 0; i < n; i++) {
cin >> x1 >> y1 >> x2 >> y2;
lines.push_back({{x1, y1},
{x2, y2}});
}
for (int i = 0; i < n; i++)
for (int j = 0; j < i; j++)
if (intersect(lines[i], lines[j]))
cnt++;
cout << cnt;
return 0;
} bool intersect(Line l1, Line l2) {
int d1 = (l1.q - l1.p) ^ (l2.p - l1.p);
int d2 = (l1.q - l1.p) ^ (l2.q - l1.p);
int d3 = (l2.q - l2.p) ^ (l1.p - l2.p);
int d4 = (l2.q - l2.p) ^ (l1.q - l2.p);
if (d1 * d2 < 0 && d3 * d4 < 0)
return true;
if (d1 == 0 && onSegment(l2.p, l1))
return true;
if (d2 == 0 && onSegment(l2.q, l1))
return true;
if (d3 == 0 && onSegment(l1.p, l2))
return true;
if (d4 == 0 && onSegment(l1.q, l2))
return true;
return false;
} bool onSegment(Point point, Line line) {
if (point.x >= min(line.p.x, line.q.x) &&
point.x <= max(line.p.x, line.q.x) &&
point.y >= min(line.p.y, line.q.y) &&
point.y <= max(line.p.y, line.q.y))
return true;
return false;
}

Graham 凸包 + 旋转卡壳

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio> using namespace std; const int MAX = 200005;
const double eps = 1e-7; struct Point {
double x, y; Point operator+(const Point &b) const {
return {x + b.x, y + b.y};
} Point operator-(const Point &b) const {
return {x - b.x, y - b.y};
} double operator^(const Point &b) const {
return x * b.y - y * b.x;
} bool operator<(const Point &b) const {
if (x != b.x)
return x < b.x;
return y < b.y;
}
}; Point p[MAX];
Point s[MAX];
int top; void selMin(int n);
int cmp(Point a, Point b);
bool equal(double a, double b);
double dis(Point a, Point b);
void graham(int n);
double s_sqr(Point a, Point b, Point c);
double diameter(); int main() {
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> p[i].x >> p[i].y;
selMin(n);
sort(p + 1, p + n, cmp);
graham(n);
printf("%.6f", sqrt(diameter())) ;
return 0;
} void selMin(int n) {
Point Min = p[0];
int IDMin = 0;
for (int i = 0; i < n; i++)
if (p[i] < Min) {
Min = p[i];
IDMin = i;
}
swap(p[0], p[IDMin]);
} int cmp(Point a, Point b) {
double x = (a - p[0]) ^ (b - p[0]);
if (x > 0)
return 1;
if (equal(x, 0) && (dis(a, p[0]) < dis(b, p[0])))
return 1;
return 0;
} double dis(Point a, Point b) {
double x = a.x - b.x;
double y = a.y - b.y;
return x * x + y * y;
} void graham(int n) {
top = 1;
s[0] = p[0];
s[1] = p[1];
for (int i = 2; i < n; i++) {
while (top > 1 && ((p[i] - s[top]) ^ (s[top - 1] - s[top])) <= 0)
top--;
s[++top] = p[i];
}
} double s_sqr(Point a, Point b, Point c) {
return fabs((a - b) ^ (c - b));
} double diameter() {
double diam = 0;
int j = 2;
s[++top] = s[0];
if (top < 3)
return dis(s[0], s[1]);
for (int i = 0; i < top - 1; i++) {
while (s_sqr(s[i], s[i + 1], s[j]) <
s_sqr(s[i], s[i + 1], s[(j + 1) % top]))
j = (j + 1) % top;
diam = max(diam, max(dis(s[i], s[j]), dis(s[i + 1], s[j])));
}
return diam;
}
bool equal(double a, double b){
return fabs(a - b) < eps;
}

其他算法

多项式乘法-FFT

#include <iostream>
#include <vector>
#include <cmath> const double Pi = acos(-1);
const int MAX = 4000005;
using namespace std;
typedef long long ll; struct Complex {
double x, y; Complex operator+(const Complex &b) const {
return {x + b.x, y + b.y};
} Complex operator-(const Complex &b) const {
return {x - b.x, y - b.y};
} Complex operator*(const Complex &b) const {
return {x * b.x - y * b.y, x * b.y + y * b.x};
}
} f[MAX], p[MAX], sav[MAX];
void dft(Complex *f, int len); void idft(Complex *f, int len); int main() {
int n, m;
cin >> n >> m;
for (int i = 0; i <= n; i++)
cin >> f[i].x;
for (int i = 0; i <= m; i++)
cin >> p[i].x;
for (m += n, n = 1; n <= m; n <<= 1);
dft(f, n);
dft(p, n);
for (int i = 0; i < n; i++)
f[i] = f[i] * p[i];
idft(f, n);
for (int i = 0; i <= m; i++)
cout << (int) (f[i].x / n + 0.49) << " ";
return 0;
} void dft(Complex *f, int len) {
if (len == 1)
return;
Complex *fl = f, *fr = f + len / 2;
for (int k = 0; k < len; k++)
sav[k] = f[k];
for (int k = 0; k < len / 2; k++) {
fl[k] = sav[k << 1];
fr[k] = sav[k << 1 | 1];
}
dft(fl, len / 2);
dft(fr, len / 2);
Complex tG = {cos(2 * Pi / len), sin(2 * Pi / len)};
Complex buf = {1, 0};
for (int k = 0; k < len / 2; k++) {
sav[k] = fl[k] + buf * fr[k];
sav[k + len / 2] = fl[k] - buf * fr[k];
buf = buf * tG;
}
for (int k = 0; k < len; k++)
f[k] = sav[k];
} void idft(Complex *f, int len) {
if (len == 1)
return;
Complex *fl = f, *fr = f + len / 2;
for (int k = 0; k < len; k++)
sav[k] = f[k];
for (int k = 0; k < len / 2; k++) {
fl[k] = sav[k << 1];
fr[k] = sav[k << 1 | 1];
}
idft(fl, len / 2);
idft(fr, len / 2);
Complex tG = {cos(2 * Pi / len), -sin(2 * Pi / len)};
Complex buf = {1, 0};
for (int k = 0; k < len / 2; k++) {
sav[k] = fl[k] + buf * fr[k];
sav[k + len / 2] = fl[k] - buf * fr[k];
buf = buf * tG;
}
for (int k = 0; k < len; k++)
f[k] = sav[k];
}

高精度乘法-FFT

#include <iostream>
#include <cmath>
#include <cstring> const double Pi = acos(-1);
const int MAX = 4000005;
using namespace std;
typedef long long ll; struct Complex {
double x, y; Complex operator+(const Complex &b) const {
return {x + b.x, y + b.y};
} Complex operator-(const Complex &b) const {
return {x - b.x, y - b.y};
} Complex operator*(const Complex &b) const {
return {x * b.x - y * b.y, x * b.y + y * b.x};
}
} f[MAX], p[MAX], sav[MAX]; ll ans[MAX];
void dft(Complex *f, int len); void idft(Complex *f, int len); int main() {
char a[MAX], b[MAX];
scanf("%s%s", a, b);
int n = strlen(a);
int m = strlen(b);
for(int i = 0; i < n; i++)
f[i].x = a[n - i - 1] - '0';
for(int i = 0; i < m; i++)
p[i].x = b[m - i - 1] - '0';
for (m += n, n = 1; n <= m; n <<= 1);
dft(f, n);
dft(p, n);
for (int i = 0; i < n; i++)
f[i] = f[i] * p[i];
idft(f, n);
for (int i = 0; i <= m; i++)
ans[i] = (ll) (f[i].x / n + 0.49);
for(int i = 0; i < MAX; i++){
ans[i + 1] += (ans[i] / 10);
ans[i] %= 10;
}
int t = MAX - 1;
while (ans[t] == 0)
t--;
while (t >= 0)
cout << ans[t--];
cout << endl;
return 0;
} void dft(Complex *f, int len) {
if (len == 1)
return;
Complex *fl = f, *fr = f + len / 2;
for (int k = 0; k < len; k++)
sav[k] = f[k];
for (int k = 0; k < len / 2; k++) {
fl[k] = sav[k << 1];
fr[k] = sav[k << 1 | 1];
}
dft(fl, len / 2);
dft(fr, len / 2);
Complex tG = {cos(2 * Pi / len), sin(2 * Pi / len)};
Complex buf = {1, 0};
for (int k = 0; k < len / 2; k++) {
sav[k] = fl[k] + buf * fr[k];
sav[k + len / 2] = fl[k] - buf * fr[k];
buf = buf * tG;
}
for (int k = 0; k < len; k++)
f[k] = sav[k];
} void idft(Complex *f, int len) {
if (len == 1)
return;
Complex *fl = f, *fr = f + len / 2;
for (int k = 0; k < len; k++)
sav[k] = f[k];
for (int k = 0; k < len / 2; k++) {
fl[k] = sav[k << 1];
fr[k] = sav[k << 1 | 1];
}
idft(fl, len / 2);
idft(fr, len / 2);
Complex tG = {cos(2 * Pi / len), -sin(2 * Pi / len)};
Complex buf = {1, 0};
for (int k = 0; k < len / 2; k++) {
sav[k] = fl[k] + buf * fr[k];
sav[k + len / 2] = fl[k] - buf * fr[k];
buf = buf * tG;
}
for (int k = 0; k < len; k++)
f[k] = sav[k];
}

KMP 字符串匹配

#include <iostream>
#include <vector>
#include <string> using namespace std; vector<int> prefix(string str); int main(){
string text;
string key;
cin >> text;
cin >> key;
int kl = key.length();
vector<int> kmp = prefix(key);
int k = 0;
for(int i = 0; i < text.length(); i++){
while (k && key[k] != text[i])
k = kmp[k - 1];
if(text[i] == key[k])
k++;
if(k == kl)
cout << i - k + 2 << endl;
}
for(auto x: kmp)
cout << x << " ";
return 0;
}
vector<int> prefix(string str){
int l = (int) str.length();
vector<int> pre(l);
for(int i = 1; i < l; i++){
int j = pre[i - 1];
while (j && str[j] != str[i])
j = pre[j - 1];
if(str[j] == str[i])
j++;
pre[i] = j;
}
return pre;
}

其它

快速幂取余

ll fast_pow_mod(ll a, ll b, ll m){
a %= m;
ll res = 1;
while (b > 0) {
if (b & 1) res = res * a % m;
a = a * a % m;
b >>= 1;
}
return res;
}

快速打质数表

vector<int> generate_prime_list(int n) {
if (n <= 2)
return vector<int>{2};
if (n <= 3)
return vector<int>{2, 3};
if (n <= 5)
return vector<int>{2, 3, 5};
vector<int> prime_list = {2, 3, 5};
int i = 1;
int x;
while (true) {
x = 6 * i + 1;
if (x > n)
break;
if (is_prime(x, prime_list))
prime_list.push_back(x);
x = 6 * i + 5;
if (x > n)
break;
if (is_prime(x, prime_list))
prime_list.push_back(x);
i++;
}
return prime_list;
} bool is_prime(int x, const vector<int> &prime_list) {
for(auto u: prime_list){
if(x % u == 0)
return false;
if(u * u > x)
return true;
}
return false;
}

鸣谢

BUAA_C++算法板子积累_动态规划、图算法、计算几何、FFT的更多相关文章

  1. 算法导论——lec 11 动态规划及应用

    和分治法一样,动态规划也是通过组合子问题的解而解决整个问题的.分治法是指将问题划分为一个一个独立的子问题,递归地求解各个子问题然后合并子问题的解而得到原问题的解.与此不同,动态规划适用于子问题不是相互 ...

  2. BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树

    BZOJ_1672_[Usaco2005 Dec]Cleaning Shifts 清理牛棚_动态规划+线段树 题意:  约翰的奶牛们从小娇生惯养,她们无法容忍牛棚里的任何脏东西.约翰发现,如果要使这群 ...

  3. 51nod_1412_AVL树的种类_动态规划

    51nod_1412_AVL树的种类_动态规划 题意: 平衡二叉树(AVL树),是指左右子树高度差至多为1的二叉树,并且该树的左右两个子树也均为AVL树. 现在问题来了,给定AVL树的节点个数n,求有 ...

  4. 五大常用算法之二:动态规划算法(DP)

    一.基本概念 动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 二.基本思想与策略 基本 ...

  5. Breaseman算法绘制圆形|中点算法绘制圆形_程序片段

    Breaseman算法绘制圆形|中点算法绘制圆形_程序片段 1. Breaseman算法绘制圆形程序 由于算法的特殊性,限制绘制第一象限部分,其他部分通过旋转绘制. void CCGProjectWo ...

  6. 【LOJ#575】【LNR#2】不等关系(容斥,动态规划,分治FFT)

    [LOJ#575][LNR#2]不等关系(容斥,动态规划,分治FFT) 题面 LOJ 题解 一个暴力\(dp\),设\(f[i][j]\)表示考虑完了前\(i\)个位置,其中最后一个数在前面所有数中排 ...

  7. python常用算法(7)——动态规划,回溯法

    引言:从斐波那契数列看动态规划 斐波那契数列:Fn = Fn-1 + Fn-2    ( n = 1,2     fib(1) = fib(2) = 1) 练习:使用递归和非递归的方法来求解斐波那契数 ...

  8. LeetCode初级算法的Python实现--动态规划

    动态规划的本质是递归:所以做题之前一定要会递归:递归式就是状态转移方程:这里将会介绍使用动态规划做题的思维方式. 统一的做题步骤: 1.用递归的方式写出代码:(此方法写的代码在leetcode中一定会 ...

  9. 『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)

    本文索引目录: 一.动态规划的基本思想 二.数字三角形.最大子段和(PTA)递归方程 三.一道区间动态规划题点拨升华动态规划思想 四.结对编程情况 一.动态规划的基本思想: 1.1 基本概念: 动态规 ...

随机推荐

  1. MySQL数据库初识、下载使用(针对库、表、记录的增删改查)

    今日内容概要 数据演变史 数据库软件的本质 MySQL简介 下载与安装 基本配置 基本SQL语句 内容详细 1.数据演变史 # 1.单独的文本文件 没有固定的存放位置和格式 文件名:user.txt ...

  2. 《操作系统导论》第14章 | 内存操作API

    内存类型 在运行一个C程序的时候,会分配两种类型的内存.第一种称为栈内存,它的申请和释放操作是编译器来隐式管理的,所以有时也称为自动内存.假设需要在func()函数中为一个整形变量x申请空间,我们只需 ...

  3. 三、Mybatis多表关联查询应用

    一对一查询 实现语句:select * from neworder o, user u where o.uid = u.id 实体Order: 接口: 配置: 测试: 一对多查询 实现语句:selec ...

  4. 日行一算(Consecutive Integer-连续整数)

    题目 题目描述 2005年的百度之星初赛有这么一道题,一个正整数有可能可以被表示为 m(m>1) 个连续正整数之和,如: 15=1+2+3+4+5 15=4+5+6 15=7+8 但现在你的任务 ...

  5. 树莓派PICO刷入MicroPython内核的两种方式

    一.MicroPython简介 MicroPython 是 Python 3编程语言的精简高效实现,其中包括 Python 标准库的一小部分,并且经过优化,可在微控制器和受限环境中运行. 可以在 25 ...

  6. [LeetCode]1528. 重新排列字符串

    给你一个字符串 s 和一个 长度相同 的整数数组 indices . 请你重新排列字符串 s ,其中第 i 个字符需要移动到 indices[i] 指示的位置. 返回重新排列后的字符串. 示例 1: ...

  7. scanf坑我的那些年

    scanf函数作为用户输入指令给计算机的一种输入方法,它的使用有如下几被坑点: scanf用法:#include<stdio.h>;scanf("格式控制符",地址表列 ...

  8. 轩辕展览-为什么要做VR虚拟展厅设计?

    沉浸感,有趣和互动体验VR虚拟展厅设计给客户带来高度的沉浸感和互动体验,给客户一种真实的感觉,让客户更愿意参与,使商家的宣传更加客观. 展示方式多样化 ,增加宣传优势在展示产品或企业时,VR全景可达到 ...

  9. [c语言]c语言中的内存分配[转]

    在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重 ...

  10. springboot页面国际化

    引入依赖pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...