联赛模拟测试 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);
	}
}
posted @ 2020-11-11 17:48  Blancа  阅读(115)  评论(0编辑  收藏  举报
哈哈,你打开了控制台,是想要看看我的秘密吗?
莫挨老子!