在纪中,不铺好蚊帐就等着第二天比赛 GG。
kal0rona
A – 鸡腿の梦境
计算几何套路题,所以不会。
其实考试的时候看得出来是判断点是否在多边形内,但是真的不会写然后就爆零了。主要原理在于跨立试验和判奇权环。
// A.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 330;
int n, head[MAX_N], current;
double ri[MAX_N];
bool vis[MAX_N][2];
struct edge
{
int to, nxt, weight;
} edges[MAX_N * MAX_N << 1];
void addpath(int src, int dst, int weight)
{
edges[current].to = dst, edges[current].nxt = head[src];
edges[current].weight = weight, head[src] = current++;
}
struct point
{
double x, y;
} pts[MAX_N];
double pow2(double x) { return x * x; }
double getDist(point &a, point &b) { return sqrt(pow2(a.x - b.x) + pow2(a.y - b.y)); }
bool judge(point &a, point &b, point &c, point &d)
{
double u, v, w, z;
u = (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y);
v = (d.x - a.x) * (b.y - a.y) - (b.x - a.x) * (d.y - a.y);
w = (a.x - c.x) * (d.y - c.y) - (d.x - c.x) * (a.y - c.y);
z = (b.x - c.x) * (d.y - c.y) - (d.x - c.x) * (b.y - c.y);
return (u * v <= 0.00001 && w * z <= 0.00001);
}
void dfs(int u, int fa, int opt)
{
if (vis[u][opt])
return;
vis[u][opt] = true;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa)
dfs(edges[i].to, u, opt ^ edges[i].weight);
}
int main()
{
point remote_point = {9024.0, 6002.0};
while (scanf("%d", &n) != EOF)
{
memset(head, -1, sizeof(head)), current = 0;
for (int i = 1; i <= n + 1; i++)
scanf("%lf%lf%lf", &pts[i].x, &pts[i].y, &ri[i]);
for (int i = 1; i <= n; i++)
ri[i] += ri[n + 1];
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (getDist(pts[i], pts[j]) < ri[i] + ri[j])
if (judge(pts[i], pts[j], pts[n + 1], remote_point))
addpath(i, j, 1), addpath(j, i, 1);
else
addpath(i, j, 0), addpath(j, i, 0);
bool flag = true;
for (int i = 1; i <= n; i++)
{
memset(vis, false, sizeof(vis));
dfs(i, 0, 0);
for (int j = 1; j <= n; j++)
if (vis[j][0] && vis[j][1])
{
flag = false;
break;
}
if (flag == false)
break;
}
puts(flag ? "YES" : "NO");
}
return 0;
}
// A.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 330;
int n, head[MAX_N], current;
double ri[MAX_N];
bool vis[MAX_N][2];
struct edge
{
int to, nxt, weight;
} edges[MAX_N * MAX_N << 1];
void addpath(int src, int dst, int weight)
{
edges[current].to = dst, edges[current].nxt = head[src];
edges[current].weight = weight, head[src] = current++;
}
struct point
{
double x, y;
} pts[MAX_N];
double pow2(double x) { return x * x; }
double getDist(point &a, point &b) { return sqrt(pow2(a.x - b.x) + pow2(a.y - b.y)); }
bool judge(point &a, point &b, point &c, point &d)
{
double u, v, w, z;
u = (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y);
v = (d.x - a.x) * (b.y - a.y) - (b.x - a.x) * (d.y - a.y);
w = (a.x - c.x) * (d.y - c.y) - (d.x - c.x) * (a.y - c.y);
z = (b.x - c.x) * (d.y - c.y) - (d.x - c.x) * (b.y - c.y);
return (u * v <= 0.00001 && w * z <= 0.00001);
}
void dfs(int u, int fa, int opt)
{
if (vis[u][opt])
return;
vis[u][opt] = true;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa)
dfs(edges[i].to, u, opt ^ edges[i].weight);
}
int main()
{
point remote_point = {9024.0, 6002.0};
while (scanf("%d", &n) != EOF)
{
memset(head, -1, sizeof(head)), current = 0;
for (int i = 1; i <= n + 1; i++)
scanf("%lf%lf%lf", &pts[i].x, &pts[i].y, &ri[i]);
for (int i = 1; i <= n; i++)
ri[i] += ri[n + 1];
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
if (getDist(pts[i], pts[j]) < ri[i] + ri[j])
if (judge(pts[i], pts[j], pts[n + 1], remote_point))
addpath(i, j, 1), addpath(j, i, 1);
else
addpath(i, j, 0), addpath(j, i, 0);
bool flag = true;
for (int i = 1; i <= n; i++)
{
memset(vis, false, sizeof(vis));
dfs(i, 0, 0);
for (int j = 1; j <= n; j++)
if (vis[j][0] && vis[j][1])
{
flag = false;
break;
}
if (flag == false)
break;
}
puts(flag ? "YES" : "NO");
}
return 0;
}
// A.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 330; int n, head[MAX_N], current; double ri[MAX_N]; bool vis[MAX_N][2]; struct edge { int to, nxt, weight; } edges[MAX_N * MAX_N << 1]; void addpath(int src, int dst, int weight) { edges[current].to = dst, edges[current].nxt = head[src]; edges[current].weight = weight, head[src] = current++; } struct point { double x, y; } pts[MAX_N]; double pow2(double x) { return x * x; } double getDist(point &a, point &b) { return sqrt(pow2(a.x - b.x) + pow2(a.y - b.y)); } bool judge(point &a, point &b, point &c, point &d) { double u, v, w, z; u = (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y); v = (d.x - a.x) * (b.y - a.y) - (b.x - a.x) * (d.y - a.y); w = (a.x - c.x) * (d.y - c.y) - (d.x - c.x) * (a.y - c.y); z = (b.x - c.x) * (d.y - c.y) - (d.x - c.x) * (b.y - c.y); return (u * v <= 0.00001 && w * z <= 0.00001); } void dfs(int u, int fa, int opt) { if (vis[u][opt]) return; vis[u][opt] = true; for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa) dfs(edges[i].to, u, opt ^ edges[i].weight); } int main() { point remote_point = {9024.0, 6002.0}; while (scanf("%d", &n) != EOF) { memset(head, -1, sizeof(head)), current = 0; for (int i = 1; i <= n + 1; i++) scanf("%lf%lf%lf", &pts[i].x, &pts[i].y, &ri[i]); for (int i = 1; i <= n; i++) ri[i] += ri[n + 1]; for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) if (getDist(pts[i], pts[j]) < ri[i] + ri[j]) if (judge(pts[i], pts[j], pts[n + 1], remote_point)) addpath(i, j, 1), addpath(j, i, 1); else addpath(i, j, 0), addpath(j, i, 0); bool flag = true; for (int i = 1; i <= n; i++) { memset(vis, false, sizeof(vis)); dfs(i, 0, 0); for (int j = 1; j <= n; j++) if (vis[j][0] && vis[j][1]) { flag = false; break; } if (flag == false) break; } puts(flag ? "YES" : "NO"); } return 0; }
B – 鸡腿の花园
我恨卡哈希。把哈希函数设置的奇怪一点就特么过了,害。
// B.cpp
#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int MAX_N = 2e5 + 200, bitnum = 133, mod1 = 1e9 + 7, mod2 = 1e9 + 9, bitlft = 23333, bitrig = 998443;
struct hash_val
{
int val1, val2;
hash_val operator+(const int &ch)
{
hash_val ret = *this;
ret.val1 = (1LL * ret.val1 + mod1 + ch) % mod1;
ret.val2 = (1LL * ret.val2 + mod2 + ch) % mod2;
return ret;
}
hash_val operator+(const hash_val &ch)
{
hash_val ret = *this;
ret.val1 = (1LL * ret.val1 + mod1 + ch.val1) % mod1;
ret.val2 = (1LL * ret.val2 + mod2 + ch.val2) % mod2;
return ret;
}
hash_val operator-(const hash_val &rhs)
{
hash_val ret = *this;
ret.val1 = (0LL + ret.val1 + mod1 - rhs.val1) % mod1;
ret.val2 = (0LL + ret.val2 + mod2 - rhs.val2) % mod2;
return ret;
}
hash_val operator*(const int &rhs)
{
hash_val ret = *this;
ret.val1 = 1LL * ret.val1 * rhs % mod1;
ret.val2 = 1LL * ret.val2 * rhs % mod2;
return ret;
}
hash_val operator*(const hash_val &rhs)
{
hash_val ret = *this;
ret.val1 = 1LL * ret.val1 * rhs.val1 % mod1;
ret.val2 = 1LL * ret.val2 * rhs.val2 % mod2;
return ret;
}
bool operator==(const hash_val &target) const { return val1 == target.val1 && val2 == target.val2; }
bool operator<(const hash_val &target) const { return val1 < target.val1 || (val1 == target.val1 && val2 < target.val2); }
};
int n, m, ch[MAX_N][2], siz[MAX_N], fa[MAX_N];
hash_val nodes[MAX_N], bpow[MAX_N];
map<hash_val, int> mp;
long long ans = 0;
void dfs(int u, int opt)
{
siz[u] = 1;
if (ch[u][0] != -1)
dfs(ch[u][0], opt), siz[u] += siz[ch[u][0]];
else
ch[u][0] = 0;
if (ch[u][1] != -1)
dfs(ch[u][1], opt), siz[u] += siz[ch[u][1]];
else
ch[u][1] = 0;
hash_val curt = hash_val{0, 0};
curt = nodes[ch[u][0]] * nodes[ch[u][0]] * bitlft + nodes[ch[u][1]] * bitrig + (siz[u] ^ siz[ch[u][1]]);
nodes[u] = curt;
if (opt == 0)
mp[nodes[u]]++;
else
ans += mp[nodes[u]];
}
void setFather(int x, int fat) { x > 0 ? fa[x] = fat : 0; }
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d%d", &ch[i][0], &ch[i][1]), setFather(ch[i][0], i), setFather(ch[i][1], i);
bpow[0] = hash_val{1, 1};
for (int i = 1; i <= max(n, m); i++)
bpow[i] = bpow[i - 1] * bitnum;
for (int i = n + 1; i <= n + m; i++)
{
scanf("%d%d", &ch[i][0], &ch[i][1]);
if (ch[i][0] != -1)
ch[i][0] += n;
if (ch[i][1] != -1)
ch[i][1] += n;
setFather(ch[i][0], i), setFather(ch[i][1], i);
}
int root1, root2;
for (int i = 1; i <= n; i++)
if (fa[i] == 0)
root1 = i;
for (int i = n + 1; i <= n + m; i++)
if (fa[i] == 0)
root2 = i;
dfs(root1, 0), dfs(root2, 1), printf("%lld\n", ans);
return 0;
}
// B.cpp
#include <bits/stdc++.h>
#define ull unsigned long long
using namespace std;
const int MAX_N = 2e5 + 200, bitnum = 133, mod1 = 1e9 + 7, mod2 = 1e9 + 9, bitlft = 23333, bitrig = 998443;
struct hash_val
{
int val1, val2;
hash_val operator+(const int &ch)
{
hash_val ret = *this;
ret.val1 = (1LL * ret.val1 + mod1 + ch) % mod1;
ret.val2 = (1LL * ret.val2 + mod2 + ch) % mod2;
return ret;
}
hash_val operator+(const hash_val &ch)
{
hash_val ret = *this;
ret.val1 = (1LL * ret.val1 + mod1 + ch.val1) % mod1;
ret.val2 = (1LL * ret.val2 + mod2 + ch.val2) % mod2;
return ret;
}
hash_val operator-(const hash_val &rhs)
{
hash_val ret = *this;
ret.val1 = (0LL + ret.val1 + mod1 - rhs.val1) % mod1;
ret.val2 = (0LL + ret.val2 + mod2 - rhs.val2) % mod2;
return ret;
}
hash_val operator*(const int &rhs)
{
hash_val ret = *this;
ret.val1 = 1LL * ret.val1 * rhs % mod1;
ret.val2 = 1LL * ret.val2 * rhs % mod2;
return ret;
}
hash_val operator*(const hash_val &rhs)
{
hash_val ret = *this;
ret.val1 = 1LL * ret.val1 * rhs.val1 % mod1;
ret.val2 = 1LL * ret.val2 * rhs.val2 % mod2;
return ret;
}
bool operator==(const hash_val &target) const { return val1 == target.val1 && val2 == target.val2; }
bool operator<(const hash_val &target) const { return val1 < target.val1 || (val1 == target.val1 && val2 < target.val2); }
};
int n, m, ch[MAX_N][2], siz[MAX_N], fa[MAX_N];
hash_val nodes[MAX_N], bpow[MAX_N];
map<hash_val, int> mp;
long long ans = 0;
void dfs(int u, int opt)
{
siz[u] = 1;
if (ch[u][0] != -1)
dfs(ch[u][0], opt), siz[u] += siz[ch[u][0]];
else
ch[u][0] = 0;
if (ch[u][1] != -1)
dfs(ch[u][1], opt), siz[u] += siz[ch[u][1]];
else
ch[u][1] = 0;
hash_val curt = hash_val{0, 0};
curt = nodes[ch[u][0]] * nodes[ch[u][0]] * bitlft + nodes[ch[u][1]] * bitrig + (siz[u] ^ siz[ch[u][1]]);
nodes[u] = curt;
if (opt == 0)
mp[nodes[u]]++;
else
ans += mp[nodes[u]];
}
void setFather(int x, int fat) { x > 0 ? fa[x] = fat : 0; }
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d%d", &ch[i][0], &ch[i][1]), setFather(ch[i][0], i), setFather(ch[i][1], i);
bpow[0] = hash_val{1, 1};
for (int i = 1; i <= max(n, m); i++)
bpow[i] = bpow[i - 1] * bitnum;
for (int i = n + 1; i <= n + m; i++)
{
scanf("%d%d", &ch[i][0], &ch[i][1]);
if (ch[i][0] != -1)
ch[i][0] += n;
if (ch[i][1] != -1)
ch[i][1] += n;
setFather(ch[i][0], i), setFather(ch[i][1], i);
}
int root1, root2;
for (int i = 1; i <= n; i++)
if (fa[i] == 0)
root1 = i;
for (int i = n + 1; i <= n + m; i++)
if (fa[i] == 0)
root2 = i;
dfs(root1, 0), dfs(root2, 1), printf("%lld\n", ans);
return 0;
}
// B.cpp #include <bits/stdc++.h> #define ull unsigned long long using namespace std; const int MAX_N = 2e5 + 200, bitnum = 133, mod1 = 1e9 + 7, mod2 = 1e9 + 9, bitlft = 23333, bitrig = 998443; struct hash_val { int val1, val2; hash_val operator+(const int &ch) { hash_val ret = *this; ret.val1 = (1LL * ret.val1 + mod1 + ch) % mod1; ret.val2 = (1LL * ret.val2 + mod2 + ch) % mod2; return ret; } hash_val operator+(const hash_val &ch) { hash_val ret = *this; ret.val1 = (1LL * ret.val1 + mod1 + ch.val1) % mod1; ret.val2 = (1LL * ret.val2 + mod2 + ch.val2) % mod2; return ret; } hash_val operator-(const hash_val &rhs) { hash_val ret = *this; ret.val1 = (0LL + ret.val1 + mod1 - rhs.val1) % mod1; ret.val2 = (0LL + ret.val2 + mod2 - rhs.val2) % mod2; return ret; } hash_val operator*(const int &rhs) { hash_val ret = *this; ret.val1 = 1LL * ret.val1 * rhs % mod1; ret.val2 = 1LL * ret.val2 * rhs % mod2; return ret; } hash_val operator*(const hash_val &rhs) { hash_val ret = *this; ret.val1 = 1LL * ret.val1 * rhs.val1 % mod1; ret.val2 = 1LL * ret.val2 * rhs.val2 % mod2; return ret; } bool operator==(const hash_val &target) const { return val1 == target.val1 && val2 == target.val2; } bool operator<(const hash_val &target) const { return val1 < target.val1 || (val1 == target.val1 && val2 < target.val2); } }; int n, m, ch[MAX_N][2], siz[MAX_N], fa[MAX_N]; hash_val nodes[MAX_N], bpow[MAX_N]; map<hash_val, int> mp; long long ans = 0; void dfs(int u, int opt) { siz[u] = 1; if (ch[u][0] != -1) dfs(ch[u][0], opt), siz[u] += siz[ch[u][0]]; else ch[u][0] = 0; if (ch[u][1] != -1) dfs(ch[u][1], opt), siz[u] += siz[ch[u][1]]; else ch[u][1] = 0; hash_val curt = hash_val{0, 0}; curt = nodes[ch[u][0]] * nodes[ch[u][0]] * bitlft + nodes[ch[u][1]] * bitrig + (siz[u] ^ siz[ch[u][1]]); nodes[u] = curt; if (opt == 0) mp[nodes[u]]++; else ans += mp[nodes[u]]; } void setFather(int x, int fat) { x > 0 ? fa[x] = fat : 0; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d%d", &ch[i][0], &ch[i][1]), setFather(ch[i][0], i), setFather(ch[i][1], i); bpow[0] = hash_val{1, 1}; for (int i = 1; i <= max(n, m); i++) bpow[i] = bpow[i - 1] * bitnum; for (int i = n + 1; i <= n + m; i++) { scanf("%d%d", &ch[i][0], &ch[i][1]); if (ch[i][0] != -1) ch[i][0] += n; if (ch[i][1] != -1) ch[i][1] += n; setFather(ch[i][0], i), setFather(ch[i][1], i); } int root1, root2; for (int i = 1; i <= n; i++) if (fa[i] == 0) root1 = i; for (int i = n + 1; i <= n + m; i++) if (fa[i] == 0) root2 = i; dfs(root1, 0), dfs(root2, 1), printf("%lld\n", ans); return 0; }
C – 鸡腿の游戏
我特么是中了邪,一直写缩点,最后发现跟 BLO 很像。
首先,按照割点的套路去写个 Tarjan。当该点为割点时,我们就需要计算其在搜索树上的 LCA 为 \(u\) 的点对方案。跟 BLO 几乎一样吧(存疑),然后就解决了(我真是个sb)。
// C.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 5e4 + 200, MAX_E = 1e5 + 200;
typedef long long ll;
int head[MAX_N], current, n, m, dfn[MAX_N], low[MAX_N], ptot, tot[MAX_N];
ll ans[MAX_N];
struct edge
{
int to, nxt;
} edges[MAX_E << 1];
void addpath(int src, int dst)
{
edges[current].to = dst, edges[current].nxt = head[src];
head[src] = current++;
}
void tarjan(int u, int fa)
{
ll cnt = 0;
dfn[u] = low[u] = ++ptot;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa)
if (dfn[edges[i].to] == 0)
{
tarjan(edges[i].to, u), low[u] = min(low[u], low[edges[i].to]);
tot[u] += tot[edges[i].to];
if (low[edges[i].to] >= dfn[u])
{
ans[u] -= cnt * tot[edges[i].to], ans[u] += 1LL * (n - tot[edges[i].to] - 1) * tot[edges[i].to];
cnt += tot[edges[i].to];
}
}
else
low[u] = min(low[u], dfn[edges[i].to]);
ans[u] += n - 1, tot[u]++;
}
int main()
{
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; i++)
{
scanf("%d%d", &u, &v);
if (u != v)
addpath(u, v), addpath(v, u);
}
for (int i = 1; i <= n; i++)
if (dfn[i] == 0)
tarjan(i, 0);
for (int i = 1; i <= n; i++)
printf("%lld\n", ans[i]);
return 0;
}
// C.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 5e4 + 200, MAX_E = 1e5 + 200;
typedef long long ll;
int head[MAX_N], current, n, m, dfn[MAX_N], low[MAX_N], ptot, tot[MAX_N];
ll ans[MAX_N];
struct edge
{
int to, nxt;
} edges[MAX_E << 1];
void addpath(int src, int dst)
{
edges[current].to = dst, edges[current].nxt = head[src];
head[src] = current++;
}
void tarjan(int u, int fa)
{
ll cnt = 0;
dfn[u] = low[u] = ++ptot;
for (int i = head[u]; i != -1; i = edges[i].nxt)
if (edges[i].to != fa)
if (dfn[edges[i].to] == 0)
{
tarjan(edges[i].to, u), low[u] = min(low[u], low[edges[i].to]);
tot[u] += tot[edges[i].to];
if (low[edges[i].to] >= dfn[u])
{
ans[u] -= cnt * tot[edges[i].to], ans[u] += 1LL * (n - tot[edges[i].to] - 1) * tot[edges[i].to];
cnt += tot[edges[i].to];
}
}
else
low[u] = min(low[u], dfn[edges[i].to]);
ans[u] += n - 1, tot[u]++;
}
int main()
{
memset(head, -1, sizeof(head));
scanf("%d%d", &n, &m);
for (int i = 1, u, v; i <= m; i++)
{
scanf("%d%d", &u, &v);
if (u != v)
addpath(u, v), addpath(v, u);
}
for (int i = 1; i <= n; i++)
if (dfn[i] == 0)
tarjan(i, 0);
for (int i = 1; i <= n; i++)
printf("%lld\n", ans[i]);
return 0;
}
// C.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = 5e4 + 200, MAX_E = 1e5 + 200; typedef long long ll; int head[MAX_N], current, n, m, dfn[MAX_N], low[MAX_N], ptot, tot[MAX_N]; ll ans[MAX_N]; struct edge { int to, nxt; } edges[MAX_E << 1]; void addpath(int src, int dst) { edges[current].to = dst, edges[current].nxt = head[src]; head[src] = current++; } void tarjan(int u, int fa) { ll cnt = 0; dfn[u] = low[u] = ++ptot; for (int i = head[u]; i != -1; i = edges[i].nxt) if (edges[i].to != fa) if (dfn[edges[i].to] == 0) { tarjan(edges[i].to, u), low[u] = min(low[u], low[edges[i].to]); tot[u] += tot[edges[i].to]; if (low[edges[i].to] >= dfn[u]) { ans[u] -= cnt * tot[edges[i].to], ans[u] += 1LL * (n - tot[edges[i].to] - 1) * tot[edges[i].to]; cnt += tot[edges[i].to]; } } else low[u] = min(low[u], dfn[edges[i].to]); ans[u] += n - 1, tot[u]++; } int main() { memset(head, -1, sizeof(head)); scanf("%d%d", &n, &m); for (int i = 1, u, v; i <= m; i++) { scanf("%d%d", &u, &v); if (u != v) addpath(u, v), addpath(v, u); } for (int i = 1; i <= n; i++) if (dfn[i] == 0) tarjan(i, 0); for (int i = 1; i <= n; i++) printf("%lld\n", ans[i]); return 0; }