..

省选联考 2020 B 卷

D1T1|卡牌游戏|100

简单的贪心。

#include <iostream>
#include <algorithm>
#include <queue>

typedef long long lxl;
typedef std::priority_queue<int> pri;

const int maxN = 1e5;

int n;
lxl a[maxN + 10];
lxl sum;
lxl ans;

int main() {
	std::cin >> n;
	for (int i = 1; i <= n; i++) std::cin >> a[i];
	for (int i = 1; i <= n; i++) {
		sum += a[i];
		if (sum > 0 && i > 1) ans += sum;
	}
	std::cout << ans << '\n';
	return 0;
}

D1T2|信号传递|30

$\mathcal O(m!)$ 暴搜。

#include <iostream>

const int maxN = 1e5;
const int maxM = 23;
const int inf = 1e9 + 10;

int n, m, k;
int s[maxN + 10];
int v[maxM + 10];
int p[maxM + 10];
int ans = inf;

void update() {
	int res = 0;
	for (int i = 1; i < n; i++) {
		int u = s[i];
		int v = s[i + 1];
		if (p[u] <= p[v]) {
			res += p[v] - p[u];
		} else {
			res += k * (p[u] + p[v]);
		}
	}
	ans = std::min(ans, res);
	return;
}

void DFS(int now) {
	if (now > m) {
		update();
		return;
	}
	for (int i = 1; i <= m; i++) {
		if (v[i]) continue;
		v[i] = true;
		p[i] = now;
		DFS(now + 1);
		v[i] = false;
	}
	return;
}

int main() {
	std::cin >> n >> m >> k;
	for (int i = 1; i <= n; i++) std::cin >> s[i];
	DFS(1);
	std::cout << ans;
	return 0;
}

D1T3|冰火战士|0

不会。

D2T1|幸运数字|85

发现奖励条件可以转化为区间修改,考虑线段树。

尝试了模块化调试。

其实没有多次询问的话可以用差分的。

不知道哪挂了 15 分。

#include <iostream>
#include <algorithm>
#include <vector>

typedef std::vector<int> vic;

const int maxN = 1e5;

int n;
struct Node {
	int t;
	int L, R;
	int A, B;
	int w;
} node[maxN + 10];

vic raw;

int a[6 * maxN + 10];
int ans;

struct SegmentTree {
	struct Node {
		int val;
		int tag;
	} node[4 * 6 * maxN + 10];

	void MakeTag(int u, int w) {
		node[u].tag ^= w;
		return;
	}

	void PushUp(int u) {
		node[u].val = std::max(node[u * 2].val, node[u * 2 + 1].val);
		return;
	}

	void PushDown(int u) {
		if (!node[u].tag) return;
		MakeTag(u * 2, node[u].tag);
		MakeTag(u * 2 + 1, node[u].tag);
		node[u].tag = 0;
		return;
	}

	///*
	void Build(int u, int l, int r) {
		if (l == r) {
			node[u].val = raw[l];
			return;
		}
		int mid = (l + r) / 2;
		Build(u * 2, l, mid);
		Build(u * 2 + 1, mid + 1, r);
		return;
	}
	//*/

	//int a[6 * maxN + 10];

	/*
	void Build(int u, int l, int r) {
		//for (int i = l; i <= r; i++) a[i] = raw[i];
		return;
	}
	*/

	///*
	void Modify(int u, int l, int r, int s, int t, int w) {
		if (s > t) return;
		if (s <= l && r <= t) {
			MakeTag(u, w);
			return;
		}
		PushDown(u);
		int mid = (l + r) / 2;
		if (s <= mid) Modify(u * 2, l, mid, s, t, w);
		if (t >= mid + 1) Modify(u * 2 + 1, mid + 1, r, s, t, w);
		return;
	}
	//*/

	/*
	void Modify(int u, int l, int r, int s, int t, int w) {
		for (int i = s; i <= t; i++) a[i] ^= w;
		return;
	}
	*/

	///*
	void Query(int u, int l, int r) {
		if (l == r) {
			a[l] = node[u].val ^ node[u].tag;
			//printf("a[%d] = %d\n", l, a[l]);
			if (a[l] > a[ans]) ans = l;
			return;
		}
		PushDown(u);
		int mid = (l + r) / 2;
		//return std::max(Query(u * 2, l, mid), Query(u * 2 + 1, mid + 1, r));
		Query(u * 2, l, mid);
		Query(u * 2 + 1, mid + 1, r);
		return;
	}
	//*/

	/*
	int Query(int u, int l, int r) {
		int ret = 0;
		for (int i = l; i <= r; i++) ret = std::max(ret, a[i]);
		return ret;
	}
	*/
} SGT;

int main() {
	std::cin >> n;
	for (int i = 1; i <= n; i++) {
		std::cin >> node[i].t;
		if (node[i].t == 1) {
			std::cin >> node[i].L >> node[i].R >> node[i].w;
			raw.push_back(node[i].L - 1);
			raw.push_back(node[i].L);
			raw.push_back(node[i].L + 1);
			raw.push_back(node[i].R - 1);
			raw.push_back(node[i].R);
			raw.push_back(node[i].R + 1);
		} else if (node[i].t == 2) {
			std::cin >> node[i].A >> node[i].w;
			raw.push_back(node[i].A - 1);
			raw.push_back(node[i].A);
			raw.push_back(node[i].A + 1);
		} else if (node[i].t == 3) {
			std::cin >> node[i].B >> node[i].w;
			raw.push_back(node[i].B - 1);
			raw.push_back(node[i].B);
			raw.push_back(node[i].B + 1);
		}
	}
	std::sort(raw.begin(), raw.end());
	raw.erase(std::unique(raw.begin(), raw.end()), raw.end());
	//for (int i = 0; i < raw.size(); i++) printf("%5d", i); printf("\n");
	//for (int i = 0; i < raw.size(); i++) printf("%5d", raw[i]); printf("\n");
	for (int i = 1; i <= n; i++) {
		if (node[i].t == 1) {
			node[i].L = std::lower_bound(raw.begin(), raw.end(), node[i].L) - raw.begin();
			node[i].R = std::lower_bound(raw.begin(), raw.end(), node[i].R) - raw.begin();
		} else if (node[i].t == 2) {
			node[i].A = std::lower_bound(raw.begin(), raw.end(), node[i].A) - raw.begin();
		} else if (node[i].t == 3) {
			node[i].B = std::lower_bound(raw.begin(), raw.end(), node[i].B) - raw.begin();
		}
	}
	//SGT.Build(1, 0, raw.size() - 1);
	for (int i = 1; i <= n; i++) {
		if (node[i].t == 1) {
			SGT.Modify(1, 0, raw.size() - 1, node[i].L, node[i].R, node[i].w);
			//printf("modify [%d, %d], %d\n", node[i].L, node[i].R, node[i].w);
		} else if (node[i].t == 2) {
			SGT.Modify(1, 0, raw.size() - 1, node[i].A, node[i].A, node[i].w);
			//printf("modify [%d, %d], %d\n", node[i].A, node[i].A, node[i].w);
		} else if (node[i].t == 3) {
			SGT.Modify(1, 0, raw.size() - 1, 0, node[i].B - 1, node[i].w);
			SGT.Modify(1, 0, raw.size() - 1, node[i].B + 1, raw.size() - 1, node[i].w);
			//printf("modify [%d, %d], %d\n", 0, node[i].B - 1, node[i].w);
			//printf("modify [%d, %d], %d\n", node[i].B + 1, raw.size() - 1, node[i].w);
		}
	}
	//std::cout << SGT.Query(1, 0, raw.size() - 1);
	SGT.Query(1, 0, raw.size() - 1);
	std::cout << a[ans] << ' ' << raw[ans] << '\n';
	return 0;
}

D2T2|消息传递|30

$\mathcal O(qn)$ 搜索。

#include <iostream>

const int maxN = 1e5;
const int maxM = 1e5;

int T;
int n, m;
int a, b;
int x, k;

namespace graph {
	struct Vertex {
		int head;
	} vertex[maxN + 10];

	struct Edge {
		int head;
		int next;
	} edge[maxN * 2 + 10];

	int ecnt;

	void addEdge(int tail, int head) {
		ecnt++;
		edge[ecnt].head = head;
		edge[ecnt].next = vertex[tail].head;
		vertex[tail].head = ecnt;
		return;
	}

	int DFS(int u, int from, int k) {
		if (k == 0) return 1;
		int ret = 0;
		for (int e = vertex[u].head; e; e = edge[e].next) {
			int v = edge[e].head;
			if (v == from) continue;
			ret += DFS(v, u, k - 1);
		}
		return ret;
	}

	void clear() {
		for (int i = 1; i <= n; i++) vertex[i].head = 0;
		ecnt = 0;
		return;
	}
}

void mian() {
	std::cin >> n >> m;
	graph::clear();
	for (int i = 1; i < n; i++) {
		std::cin >> a >> b;
		graph::addEdge(a, b);
		graph::addEdge(b, a);
	}
	for (int i = 1; i <= m; i++) {
		std::cin >> x >> k;
		std::cout << graph::DFS(x, 0, k) << '\n';
	}
	return;
}

int main() {
	std::cin >> T;
	while (T--) mian();
	return 0;
}

D2T3|丁香之路

没打暴力,但是有部分分。

#include <iostream>
#include <algorithm>

const int maxN = 2500;
const int maxM = 3123750;
const int inf = 1e9 + 10;

int abs(int x) {
	if (x < 0) x = - x;
	return x;
}

int n, m, s;
int u, v;

namespace M0 {
	void mian() {
		for (int i = 1; i <= n; i++) std::cout << abs(i - s) << ' ';
		return;
	}
}

namespace M1 {
	void mian() {
		for (int i = 1; i <= n; i++) {
			int ans = inf;
			int uv = abs(u - v);
			int su = abs(u - s);
			int sv = abs(v - s);
			int ui = abs(u - i);
			int vi = abs(v - i);
			ans = std::min(ans, su + uv + vi);
			ans = std::min(ans, sv + uv + ui);
			ans = std::min(ans, su + uv + uv + ui);
			ans = std::min(ans, sv + uv + uv + vi);
			std::cout << ans << ' ';
		}
	}
}

int main() {
	std::cin >> n >> m >> s;
	for (int i = 1; i <= m; i++) std::cin >> u >> v;
	if (m == 0) M0::mian();
	if (m == 1) M1::mian();
	return 0;
}

总结

  • 模块化调试真的好用。
  • 暴力与部分分还是值得多思考。