2022“杭电杯”中国大学生算法设计超级联赛(5)

Slipper

给一颗以1为根有边权的数,且当\(|dep_u-dep_v|==k\)\(u\)可以花费\(p\)走到\(v\),求s到t的最短路。
每一个dep建两个点一个从树上的点连入,一个连向树上的点,中间连花费p的边
前向星比vector快了不止一倍

using IO::gi;
using IO::pi;
using IO::pc;
const int N = 1000000 + 5;
priority_queue<pair<ll, int>, vector<pair<ll, int> >, greater<pair<ll, int> > > q;
bool vis[N + N + N];
ll dis[N + N + N];
int n, fir1[N], ecnt1, fir[N + N + N], ecnt;
struct Edge {
	int to, nxt, w;
} edge1[N << 1], edge[N * 6];
void addedge(int u, int v, int w) {
	edge[++ecnt] = (Edge){v, fir[u], w}; fir[u] = ecnt;
}
void dfs(int u, int fa, int dep) {
	addedge(u, dep + n, 0);
	addedge(dep + n + n, u, 0);
	for (int e = fir1[u]; e; e = edge1[e].nxt) {
		int v = edge1[e].to;
		if (v == fa) continue;
		dfs(v, u, dep + 1);
	}
}
void Add(int u, int v) {
	edge1[++ecnt1] = (Edge){v, fir1[u], 0}; fir1[u] = ecnt1;
	edge1[++ecnt1] = (Edge){u, fir1[v], 0}; fir1[v] = ecnt1;
}
int main() {
//	freopen("a.in", "r", stdin);
	int T = gi();
	while (T--) {
		n = gi();
		for (int i = 1; i <= n; ++i) fir1[i] = 0;
		for (int i = 1; i <= n + n + n; ++i) fir[i] = 0;
		ecnt1 = 0, ecnt = 0;
		for (int i = 1; i < n; ++i) {
			int u = gi(), v = gi(), w = gi();
			Add(u, v);
			addedge(u, v, w);
			addedge(v, u, w);
		}
		dfs(1, 0, 1);
		int k = gi(), p = gi();
		for (int i = 1; i <= n - k; ++i) {
			addedge(n + i, n + n + i + k, p);
			addedge(n + n + i + k, n + i, p);
		}
		int s = gi(), t = gi();
		for (int i = 1; i <= n + n + n; ++i) {
			dis[i] = 1e18;
			vis[i] = 0;
		}
		q.emplace(dis[s] = 0, s);
		while (q.size()) {
			int u = q.top().second; q.pop();
			if (vis[u]) continue;
			vis[u] = 1;
			for (int e = fir[u]; e; e = edge[e].nxt) {
				int v = edge[e].to;
				if (dis[v] > dis[u] + edge[e].w) q.emplace(dis[v] = dis[u] + edge[e].w, v);
			}
		}
		printf("%lld\n", dis[t]);
	}
	return 0;
}

Bragging Dice

题目读错,自闭2个h

#include <bits/stdc++.h>
using namespace std;
int n, x, A[10], B[10];
int main() {
	int T; scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		for (int i = 1; i <= 6; ++i) A[i] = B[i] = 0;
		bool uniA = 1, uniB = 1;
		for (int i = 1; i <= n; ++i) {
			int x; scanf("%d", &x);
			if (A[x]) uniA = 0;
			A[x] = 1;
		}
		for (int i = 1; i <= n; ++i) {
			int x; scanf("%d", &x);
			if (B[x]) uniB = 0;
			B[x] = 1;
		}
		bool flag = 0;
		for (int i = 2; i <= 6; ++i) flag |= A[i] && B[i];
		if (uniA && uniB) puts("Just a game of chance.");
		else puts("Win!");
	}
	return 0;
}

Buy Figurines

n个人去m个窗口购物,每个人有到达时间\(a_i\),花费时间\(s_i\),当有一人到达时,他会去等待人数最少的窗口(人数一样去编号小的)等待。问最后一人离开的时间。
用STL模拟,一个堆存每个人的结束时间和窗口,一个set存人数和窗口。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct A {
	int a, s;
} p[200005];
priority_queue<pair<ll, int>, vector<pair<ll, int> >, greater<pair<ll, int> > > hp;   // edtime windows
set<pair<int, int> > win; // num_p windows
ll ed[200005];
int n, m, cnt[200005];
int main() {
	int T; scanf("%d", &T);
	while (T--) {
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; ++i) scanf("%d%d", &p[i].a, &p[i].s);
		sort(p + 1, p + n + 1, [](const A &l, const A &r) { return l.a < r.a; });
		while (hp.size()) hp.pop();
		win.clear();
		for (int i = 1; i <= m; ++i) {
			ed[i] = 1;
			win.emplace(cnt[i] = 0, i);
		}
		for (int i = 1; i <= n; ++i) {
			while (hp.size() && hp.top().first <= p[i].a) {
				int tmp = hp.top().second;
				win.erase(make_pair(cnt[tmp]--, tmp));
				win.emplace(cnt[tmp], tmp);
				hp.pop();
			}
			int tmp = win.begin()->second;
			win.erase(win.begin());
			win.emplace(++cnt[tmp], tmp);
			hp.emplace(ed[tmp] = max(ed[tmp], (ll)p[i].a) + p[i].s, tmp);
		}
		ll ans = 0;
		for (int i = 1; i <= m; ++i) ans = max(ans, ed[i]);
		printf("%lld\n", ans);
	}
	return 0;
}
posted @ 2022-08-05 23:44  chenyilei  阅读(28)  评论(0编辑  收藏  举报