2021-team4-template
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
= 路径压缩trie =
#include <bits/stdc++.h>
using namespace std;
int n, id[100005];
string s[100005];
int tot, par[200000], pos[100005], mx[200000], g[200000];
bool vis[200000];
void pro(int x, int l, int r, int d) {
int cnt = 0;
for (; l <= r && s[id[l]].size() == d; l ++) {
pos[id[l]] = x;
cnt = 1;
}
cnt += l <= r;
cnt += l <= r && s[id[l]][d] != s[id[r]][d];
for (int i = l, j; i <= r; i = j + 1) {
j = i;
while (j < r && s[id[i]][d] == s[id[j + 1]][d])
j ++;
if (cnt == 1)
pro(x, i, j, d + 1), vis[x] = 1;
else {
char v = s[id[i]][d];
int c = islower(v) ? v - 'a' : isupper(v) ? 26 + v - 'A' : isdigit(v) ? 52 + v - '0' : v == '.' ? 62 : 63;
int y = ++ tot;
par[y] = x;
pro(y, i, j, d + 1);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("a.in", "r", stdin);
#endif
cin.tie(0)->sync_with_stdio(0);
cin >> n;
for (int i = 1; i <= n; i ++)
cin >> s[i];
for (int i = 1; i <= n; i ++)
id[i] = i;
sort(id + 1, id + n + 1, [&](int i, int j) {
return s[i] < s[j];
});
tot = 1, pro(1, 1, n, 0);
assert(tot == 2 * n - 1);
for (int i = 1; i <= n; i ++) {
for (int x = pos[i]; x; x = par[x])
mx[x] = i;
}
for (int i = 1; i <= n; i ++) {
int x = pos[i];
while (par[x] > (vis[1] ? 0 : 1) && mx[par[x]] == i)
x = par[x];
int tmp = 1 - g[x];
for (int y = x; y; y = par[y])
g[y] += tmp;
printf("%d\n", g[1]);
}
return 0;
}
= hungary =
#include <bits/stdc++.h>
using namespace std;
int n, m, f[105][105], K, cons[1005][3], lk[1005], used[1005];
vector<int> g[1005];
int hungary(int i) {
for (int j : g[i])
if (!used[j]) {
used[j] = 1;
if (lk[j] == 0 || hungary(lk[j])) {
lk[j] = i;
return 1;
}
}
return 0;
}
int main() {
// freopen("b.in", "r", stdin);
scanf("%d%d%d", &n, &m, &K);
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
f[i][j] = (i != j) * 1e8;
for (int i = 1; i <= m; i ++) {
int x, y, d;
scanf("%d%d%d", &x, &y, &d);
f[x][y] = min(f[x][y], d);
}
for (int k = 1; k <= n; k ++)
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
for (int i = 1; i <= K; i ++)
scanf("%d%d%d", cons[i], cons[i] + 1, cons[i] + 2);
for (int i = 1; i <= K; i ++)
for (int j = 1; j <= K; j ++)
if (i != j && cons[i][2] + f[cons[i][0]][cons[i][1]] + f[cons[i][1]][cons[j][0]] <= cons[j][2])
g[i].push_back(j);
int ans = K;
for (int i = 1; i <= K; i ++) {
memset(used, 0, sizeof used);
ans -= hungary(i);
}
printf("%d\n", ans);
return 0;
}
= 求直线外一点与凸包切点 =
//8.13 2021NowcoderTraining_816_J
#include <bits/stdc++.h>
using namespace std;
#define int long long
typedef pair<int, int> pii;
const int INF = 1e9;
struct Point {
int x, y;
Point(): x(0), y(0) {}
Point(int x, int y): x(x), y(y) {}
int det(const Point &u) { return x * u.y - y * u.x; }
};
bool operator<(const Point &u, const Point &v) { return u.x == v.x ? u.y < v.y : u.x < v.x; }
bool operator>(const Point &u, const Point &v) { return u.x == v.x ? u.y > v.y : u.x > v.x; }
Point operator-(const Point &u, const Point &v) { return Point(u.x - v.x, u.y - v.y); }
struct Convex {
int n;
vector<Point> a, upper, lower;
void Init(int _n) {
a.resize(_n);
n = _n;
int mn = 0;
for (int i = 0; i < n; ++i) {
scanf("%lld%lld", &a[i].x, &a[i].y);
if (a[i] < a[mn]) mn = i;
}
rotate(a.begin(), a.begin() + mn, a.end());
int ptr = 0;
for (int i = 1; i < n; ++i) if (a[ptr] < a[i]) ptr = i;
for (int i = 0; i <= ptr; ++i) lower.push_back(a[i]);
for (int i = ptr; i < n; ++i) upper.push_back(a[i]);
upper.push_back(a[0]);
}
int sign(int x) { return x < 0 ? -1 : x > 0; }
void update_tangent(const Point &p, int id, int &i0, int &i1) {
if ((a[i0] - p).det(a[id] - p) > 0) i0 = id;
if ((a[i1] - p).det(a[id] - p) < 0) i1 = id;
}
void binary_search(int l, int r, Point p, int &i0, int &i1) {
if (l == r) return;
update_tangent(p, l % n, i0, i1);
int sl = sign((a[l % n] - p).det(a[(l + 1) % n] - p));
for (; l + 1 < r; ) {
int mid = (l + r) / 2;
int smid = sign((a[mid % n] - p).det(a[(mid + 1) % n] - p));
if (smid == sl) l = mid; else r = mid;
}
update_tangent(p, r % n, i0, i1);
}
pii get_tangent(Point p) {
int i0 = 0, i1 = 0;
int id = lower_bound(lower.begin(), lower.end(), p) - lower.begin();
binary_search(0, id, p, i0, i1);
binary_search(id, (int)lower.size(), p, i0, i1);
id = lower_bound(upper.begin(), upper.end(), p, greater<Point>()) - upper.begin();
binary_search((int)lower.size() - 1, (int)lower.size() - 1 + id, p, i0, i1);
binary_search((int)lower.size() - 1 + id, (int)lower.size() - 1 + (int)upper.size(), p, i0, i1);
return pii(i0, i1);
}
} con;
const int N = 2e5 + 10;
int n, m;
int f[N][20], d[N][20];
signed main() {
scanf("%lld%lld", &n, &m);
con.Init(n);
for (int i = 1, x, y; i <= m; ++i) {
scanf("%lld%lld", &x, &y);
pii tmp = con.get_tangent(Point(x, y));
if (tmp.second < tmp.first) tmp.second += n;
}
}
路径压缩trie
#include
using namespace std;
int n, id[100005];
string s[100005];
int tot, par[200000], pos[100005], mx[200000], g[200000];
bool vis[200000];
void pro(int x, int l, int r, int d) {
int cnt = 0;
for (; l <= r && s[id[l]].size() == d; l ++) {
pos[id[l]] = x;
cnt = 1;
}
cnt += l <= r;
cnt += l <= r && s[id[l]][d] != s[id[r]][d];
for (int i = l, j; i <= r; i = j + 1) {
j = i;
while (j < r && s[id[i]][d] == s[id[j + 1]][d])
j ++;
if (cnt == 1)
pro(x, i, j, d + 1), vis[x] = 1;
else {
char v = s[id[i]][d];
int c = islower(v) ? v - 'a' : isupper(v) ? 26 + v - 'A' : isdigit(v) ? 52 + v - '0' : v == '.' ? 62 : 63;
int y = ++ tot;
par[y] = x;
pro(y, i, j, d + 1);
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("a.in", "r", stdin);
#endif
cin.tie(0)->sync_with_stdio(0);
cin >> n;
for (int i = 1; i <= n; i ++)
cin >> s[i];
for (int i = 1; i <= n; i ++)
id[i] = i;
sort(id + 1, id + n + 1, [&](int i, int j) {
return s[i] < s[j];
});
tot = 1, pro(1, 1, n, 0);
assert(tot == 2 * n - 1);
for (int i = 1; i <= n; i ++) {
for (int x = pos[i]; x; x = par[x])
mx[x] = i;
}
for (int i = 1; i <= n; i ++) {
int x = pos[i];
while (par[x] > (vis[1] ? 0 : 1) && mx[par[x]] == i)
x = par[x];
int tmp = 1 - g[x];
for (int y = x; y; y = par[y])
g[y] += tmp;
printf("%d\n", g[1]);
}
return 0;
}
hungary
#include
using namespace std;
int n, m, f[105][105], K, cons[1005][3], lk[1005], used[1005];
vector
int hungary(int i) {
for (int j : g[i])
if (!used[j]) {
used[j] = 1;
if (lk[j] == 0 || hungary(lk[j])) {
lk[j] = i;
return 1;
}
}
return 0;
}
int main() {
// freopen("b.in", "r", stdin);
scanf("%d%d%d", &n, &m, &K);
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
f[i][j] = (i != j) * 1e8;
for (int i = 1; i <= m; i ++) {
int x, y, d;
scanf("%d%d%d", &x, &y, &d);
f[x][y] = min(f[x][y], d);
}
for (int k = 1; k <= n; k ++)
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= n; j ++)
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
for (int i = 1; i <= K; i ++)
scanf("%d%d%d", cons[i], cons[i] + 1, cons[i] + 2);
for (int i = 1; i <= K; i ++)
for (int j = 1; j <= K; j ++)
if (i != j && cons[i][2] + f[cons[i][0]][cons[i][1]] + f[cons[i][1]][cons[j][0]] <= cons[j][2])
g[i].push_back(j);
int ans = K;
for (int i = 1; i <= K; i ++) {
memset(used, 0, sizeof used);
ans -= hungary(i);
}
printf("%d\n", ans);
return 0;
}
求直线外一点与凸包切点
//8.13 2021NowcoderTraining_816_J
#include
using namespace std;
#define int long long
typedef pair
const int INF = 1e9;
struct Point {
int x, y;
Point(): x(0), y(0) {}
Point(int x, int y): x(x), y(y) {}
int det(const Point &u) { return x * u.y - y * u.x; }
};
bool operator<(const Point &u, const Point &v) { return u.x == v.x ? u.y < v.y : u.x < v.x; }
bool operator>(const Point &u, const Point &v) { return u.x == v.x ? u.y > v.y : u.x > v.x; }
Point operator-(const Point &u, const Point &v) { return Point(u.x - v.x, u.y - v.y); }
struct Convex {
int n;
vector
void Init(int _n) {
a.resize(_n);
n = _n;
int mn = 0;
for (int i = 0; i < n; ++i) {
scanf("%lld%lld", &a[i].x, &a[i].y);
if (a[i] < a[mn]) mn = i;
}
rotate(a.begin(), a.begin() + mn, a.end());
int ptr = 0;
for (int i = 1; i < n; ++i) if (a[ptr] < a[i]) ptr = i;
for (int i = 0; i <= ptr; ++i) lower.push_back(a[i]);
for (int i = ptr; i < n; ++i) upper.push_back(a[i]);
upper.push_back(a[0]);
}
int sign(int x) { return x < 0 ? -1 : x > 0; }
void update_tangent(const Point &p, int id, int &i0, int &i1) {
if ((a[i0] - p).det(a[id] - p) > 0) i0 = id;
if ((a[i1] - p).det(a[id] - p) < 0) i1 = id;
}
void binary_search(int l, int r, Point p, int &i0, int &i1) {
if (l == r) return;
update_tangent(p, l % n, i0, i1);
int sl = sign((a[l % n] - p).det(a[(l + 1) % n] - p));
for (; l + 1 < r; ) {
int mid = (l + r) / 2;
int smid = sign((a[mid % n] - p).det(a[(mid + 1) % n] - p));
if (smid == sl) l = mid; else r = mid;
}
update_tangent(p, r % n, i0, i1);
}
pii get_tangent(Point p) {
int i0 = 0, i1 = 0;
int id = lower_bound(lower.begin(), lower.end(), p) - lower.begin();
binary_search(0, id, p, i0, i1);
binary_search(id, (int)lower.size(), p, i0, i1);
id = lower_bound(upper.begin(), upper.end(), p, greater
binary_search((int)lower.size() - 1, (int)lower.size() - 1 + id, p, i0, i1);
binary_search((int)lower.size() - 1 + id, (int)lower.size() - 1 + (int)upper.size(), p, i0, i1);
return pii(i0, i1);
}
} con;
const int N = 2e5 + 10;
int n, m;
int f[N][20], d[N][20];
signed main() {
scanf("%lld%lld", &n, &m);
con.Init(n);
for (int i = 1, x, y; i <= m; ++i) {
scanf("%lld%lld", &x, &y);
pii tmp = con.get_tangent(Point(x, y));
if (tmp.second < tmp.first) tmp.second += n;
}
}