联赛模拟测试 32 题解
前言:
为了应付skyh的检查,鸽子博主被迫再次写题解
T1 : 循环依赖
一眼sb题,判断一下有没有环即可,就是读入有点恶心
代码实现
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <map>
using namespace std;
const int maxn = 5e5 + 50;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
map <unsigned long long, unsigned long long> mp;
int cnt, T , n;
unsigned long long base, now;
char S[20], C;
unsigned long long gethash (char S[]) {
int len = strlen (S + 1);
unsigned long long Hash = 0;
for (register int i = 1; i <= len; i++) {
Hash *= 233;
Hash += S[i];
}
return Hash;
}
struct Edge {
int to, next;
} edge[maxn];
int tot, head[maxn];
void addedge (int a, int b) {
edge[++tot].to = b;
edge[tot].next = head[a];
head[a] = tot;
}
int stk[maxn], top, dfn_clock;
int belong[maxn], low[maxn], dfn[maxn], scc_cnt, siz[maxn];
int sta[maxn], tp;
void tarjan (int u) {
low[u] = dfn[u] = ++dfn_clock;
sta[++tp] = u;
for (register int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (!dfn[v]) {
tarjan (v);
low[u] = min(low[u], low[v]);
} else if (!belong[v]) {
low[u] = min (low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
++scc_cnt;
while (1) {
int x = sta[tp--];
belong[x] = scc_cnt;
siz[scc_cnt]++;
if (x == u) break;
}
}
}
bool judge;
int main () {
freopen ("dependency.in", "r", stdin);
freopen ("dependency.out", "w", stdout);
T = read();
while (T--) {
n = read();
judge = false;
for (register int i = 1; i <= n; i++) {
scanf ("%s", S + 1);
C = getchar();
base = gethash(S);
if (mp[base] == 0) mp[base] = ++cnt;
base = mp[base], stk[++top] = base;
while (1) {
if (C == '\n') break;
scanf ("%s", S + 1);
now = gethash(S);
if (mp[now] == 0) mp[now] = ++cnt;
now = mp[now];
addedge (base, now);
if (base == now) {
judge = true;
}
stk[++top] = now;
C = getchar();
}
}
for (register int i = 1; i <= top; i++) {
if (dfn[stk[i]]) continue;
tarjan (stk[i]);
}
for (register int i = 1; i <= scc_cnt; i++) {
if (siz[i] > 1) {
judge = true;
}
}
if (judge == true) {
puts("Yes");
} else {
puts("No");
}
tot = 0;
scc_cnt = 0;
for (register int i = 1; i <= top; i++) {
belong[stk[i]] = 0;
siz[i] = 0;
low[stk[i]] = dfn[stk[i]] = 0;
head[stk[i]] = 0;
sta[i] = 0;
}
tp = 0;
top = 0;
dfn_clock = 0;
}
return 0;
}
T2 : A
维护一个凸包
在 x > 0 的时候就让 ax + b 取最大, 在x < 0 的时候就让ax + b 取最小
维护两个凸包就好了,注意向哪儿取整的问题
代码实现
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
#define int long long
const int maxn = 5e5 + 50;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
int n, q;
int top1, top2;
struct Node {
int l;
int a, b;
} stk1[maxn], stk2[maxn];
struct Line {
int a, b;
} line[maxn];
struct Ask {
int id, x;
long long val;
} ask[maxn];
long long ans[maxn];
inline bool cmp1 (Line A, Line B) {return A.a == B.a ? A.b < B.b : A.a > B.a;}
inline bool cmp2 (Line A, Line B) {return A.a == B.a ? A.b > B.b : A.a < B.a;}
inline bool Cmp (Ask A, Ask B) {return A.x < B.x;}
inline int getx (int a, int b, int c, int d) {
if ((d - b) % (a - c) == 0) {
return (d - b) / (a - c);
}
if ((d - b) / (a - c) < 0) return (d - b) / (a - c);
else return (d - b) / (a - c) + 1;
}
signed main () {
freopen ("A.in", "r", stdin);
freopen ("A.out", "w", stdout);
n = read(), q = read();
for (register int i = 1; i <= n; i++) {
line[i].a = read(), line[i].b = read();
}
//上凸
sort (line + 1, line + 1 + n, cmp1);
stk1[++top1].a = line[1].a;
stk1[top1].b = line[1].b;
stk1[top1].l = -0x3f3f3f3f;
for (register int i = 2; i <= n; i++) {
if (line[i].a == stk1[top1].a) continue;
int x = getx (line[i].a, line[i].b, stk1[top1].a, stk1[top1].b);
while (x <= stk1[top1].l) {
top1--;
x = getx (line[i].a, line[i].b, stk1[top1].a, stk1[top1].b);
}
++top1;
stk1[top1].a = line[i].a, stk1[top1].b = line[i].b, stk1[top1].l = x;
}
//下凸
sort (line + 1, line + 1 + n, cmp2);
stk2[++top2].a = line[1].a;
stk2[top2].b = line[1].b;
stk2[top2].l = -0x3f3f3f3f;
for (register int i = 2; i <= n; i++) {
if (line[i].a == stk2[top2].a) continue;
int x = getx (line[i].a, line[i].b, stk2[top2].a, stk2[top2].b);
while (x <= stk2[top2].l) {
top2--;
x = getx (line[i].a, line[i].b, stk2[top2].a, stk2[top2].b);
}
++top2;
stk2[top2].a = line[i].a, stk2[top2].b = line[i].b, stk2[top2].l = x;
}
for (register int i = 1; i <= q; i++) {
ask[i].x = read();
ask[i].id = i;
}
sort (ask + 1, ask + 1 + q, Cmp);
int oper = 1;
int r = 1;
while (ask[oper].x < 0) {
while (stk1[r + 1].l <= ask[oper].x && r < top1) r++;
ans[ask[oper].id] = ask[oper].x * ask[oper].x * stk1[r].a + ask[oper].x * stk1[r].b;
oper++;
}
r = 1;
while (oper <= q) {
while (stk2[r + 1].l <= ask[oper].x && r < top2) r++;
ans[ask[oper].id] = ask[oper].x * ask[oper].x * stk2[r].a + ask[oper].x * stk2[r].b;
oper++;
}
for (register int i = 1; i <= q; i++) {
printf ("%lld\n", ans[i]);
}
return 0;
}
T3 : B
都是1的情况找规律就好了,1, 2, 4 的数据点可以记忆化一下。
代码实现
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 5e5 + 5, mod = 323232323;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
int n, a[maxn], p[maxn], s, inv[maxn], mx, f[10000000];
bool g = 1;
int Dfs(int S) {
int tot = 0, &s = f[S];
if (s) return s;
if (S % p[1] == 0) return 0;
for (int i = 1; i <= n; ++i) {
int x = S % p[i] / p[i-1];
if (!x) continue;
tot++;
if ((s += Dfs(S - p[i-1]) + 1) >= mod) s -= mod;
}
return s = 1LL * s * inv[tot] % mod;
}
int main() {
freopen("B.in", "r", stdin), freopen("B.out", "w", stdout);
n = read();
for (int i = 1; i <= n; ++i) {
a[i] = read();
if (a[i] > mx) mx = a[i];
if (a[i] != 1) g = 0;
}
mx++;
p[0] = inv[1] = 1;
for (int i = 2; i <= n; ++i)
inv[i] = 1LL * (mod - mod / i) * inv[mod%i] % mod;
for (int i = 1; i <= n; ++i) {
p[i] = p[i-1] * mx;
s += a[i] * p[i-1];
}
if (g) return printf("%lld\n", 1LL * (n + 1) * inv[2] % mod), 0;
printf("%d\n", Dfs(s));
return 0;
}
t4 : C
不会第4个数据点和第8个数据点,但是貌似暴力跑过第8个数据点了?
赛时没算内存然后炸了,草
然后第四个数据点还是不会写,先咕了,等会了再向skyh报告
然后扔个40分代码(逃)
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int k = 0, f = 1; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) k = k * 10 + ch - '0';
return k * f;
}
const int maxn = 6e5 + 100;
struct node { int to, next; } e[maxn];
int head[maxn], ecnt = 0;
void add(int u, int v) { e[++ecnt] = (node){v, head[u]}; head[u] = ecnt; }
int size[maxn], depth[maxn], fa[maxn], top[maxn], a[maxn], son[maxn];
void dfs1(int u, int f) {
size[u] = 1;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v == f) continue;
fa[v] = u;
depth[v] = depth[u] + 1;
dfs1(v, u);
size[u] += size[v];
if (size[u] > size[son[u]]) son[u] = v;
}
}
void dfs2(int u, int t) {
top[u] = t;
if (son[u]) dfs2(son[u], t);
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
int lca(int u, int v) {
while (top[u] != top[v]) {
if (depth[top[u]] > depth[top[v]]) {
u = fa[top[u]];
} else {
v = fa[top[v]];
}
}
return depth[u] < depth[v] ? u : v;
}
struct edge { int u, v; } Q[maxn];
int Ans[maxn];
void dfs(int u, int f) {
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
depth[v] = depth[u] + 1;
Ans[v] = Ans[u] + (depth[v] | a[v]);
dfs(v, u);
}
}
int main() {
freopen("C.in", "r", stdin);
freopen("C.out", "w", stdout);
int n = read(), q = read(), flag = 0;
for (int i = 1; i <= n; i++) a[i] = read();
for (int i = 1; i < n; i++) {
int u = read(), v = read();
add(u, v), add(v, u);
}
for (int i = 1; i <= q; i++) {
Q[i].u = read(), Q[i].v = read();
if (Q[i].v != 1) flag = 1;
}
dfs1(1, 0);
dfs2(1, 1);
for (int i = 1; i <= q; i++) {
int u = Q[i].u, v = Q[i].v;
int LCA = lca(u, v), d = 0;
long long ans = 0;
int dis = depth[u] + depth[v] - 2 * depth[LCA];
for (; u != fa[LCA]; u = fa[u], d++) ans += (d | a[u]);
d = 0;
for (; v != LCA; v = fa[v], d++) ans += ((dis - d) | a[v]);
printf("%lld\n", ans);
}
}