「ZHYOI」Round 1比赛总结

第一次打洛谷比赛,还是大佬们出题,打的还不错。

比赛过程

A 题很显然是 \(O(n)\) 的,本来想打一个暴力,但是发现不会打,于是直接去想正解了,想了一会儿就出来了。

B 题很显然是找规律,先打了一个暴力,然后发现一些规律,写一写就出来了,然后一些小细节调了一会儿,然后就过了。

这是过去了 1 个小时感觉打的挺好,就满怀希望的看了一下第三题,然后就自闭了,想了一下发现不会,暴力也没啥思路,决定跳过。

第四题更没思路,不过惊讶的发现输出 1 有 10 分!!

在某位大佬的推荐下,决定去写第五题,写了 200 行的树剖+线段树+广搜,然后发现只有 30 分 ? 发现是没开 long long ,改了后就是 50 分了, 后面都超时了,这题看意思是过不了了, 就没搞了。

回头看第三题,想到一个 40 分的广搜,写了一会儿后发现竟然写对了,就拿了 40 分。

然后就开始摆烂到比赛结束。

最终排名:\(\text{rk41}\)

最终得分:\(\text{300pts}\)

远远超出预期。

题目总结

「ZHYOI-1」交作业

题目链接:「ZHYOI-1」交作业

这题其实很简单,我们只要找到第一个交不上作业的人,后面的都交不上。一个人如果想要叫上作业,那么在他交作业的时间段之前的作业没登记完,而登记的速度是每个时间一个,所以直接判断即可。

时间复杂度:\(O(n)\)

code

#include <bits/stdc++.h>
using namespace std;
inline long long read() {
	register long long x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch <= '9' && ch >= '0') {
		x = x * 10 + (ch - '0');
		ch = getchar();
	}
	return x * f;
}
inline void write(int x) {
	if (x < 0)
		putchar('-'), x = -x;
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}
int n;
long long p, p2;
int main() {
	n = read();
	bool f = false;
	for (int i = 1; i <= n; i++) {
		p = read();
		if (p - (i - 1) > 0 && p != p2) {
			write(n - i + 1);
			f = true;
			break;
		}
		p2 = p;
	}
	if (!f)
		putchar('0');
	return 0;
}

「ZHYOI-1」组合环

题目链接:「ZHYOI-1」组合环

这题其实不难,先输出 \(1-n\) , 然后在算出每个数剩下的出现次数,先考虑 \(n-1\) ,他只能和 \(n-2\) 相邻,所以直接输出 \({n \choose n-1}-1\)\(n-1\)\(n-2\) 即可,以此类推。

时间复杂度:\(O(2^n)\)

code

#include <bits/stdc++.h>
using namespace std;
inline int read() {
	register int x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch <= '9' && ch >= '0') {
		x = x * 10 + (ch - '0');
		ch = getchar();
	}
	return x * f;
}
inline void write(int x) {
	if (x < 0)
		putchar('-'), x = -x;
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}
int rec[30][30] = {{0}};
long long C(int n, int m) {
	if (rec[n][m] != 0)
		return rec[n][m];
	if (n == m || m == 0)return rec[n][m] = 1;
	return rec[n][m] = C(n - 1, m - 1) + C(n - 1, m);
}
int n;
int cnt[30] = {0};
int main() {
	n = read();
	for (int i = 1; i <= n; i++)
		write(i), putchar(' ');
	for (int i = 1; i <= n; i++)
		cnt[i] = C(n, i) - 1;
	for (int i = n - 1; i >= 1; i--) {
		for (int j = 1; j <= cnt[i]; j++) 
			if (i % 2 == n % 2)
				write(i - 1), putchar(' '), write(i), putchar(' ');
			else
				write(i), putchar(' '), write(i - 1), putchar(' '); 
		cnt[i - 1] -= cnt[i];
	}
	if (n % 2 == 1)
		putchar('0');
	return 0;
} 

「ZHYOI-1」石头

题目链接:「ZHYOI-1」石头

这题我不会正解,但是会暴力。对于 \(n,m \le 4\) 的情况,我们可以暴力广搜,搞一个结构体记录操作和当前数组,当数组只有一个数不为 0 时即可结束,当然,这只能得 \(40\) 分。

时间复杂度: \(\text{I don't know}\)

code

#include <bits/stdc++.h>
using namespace std;
int n, m;
int a[100005] = {0};
struct Node {
	vector<pair<int, int> > op;
	vector<int> array;
	Node () {
		vector<pair<int, int> >().swap(op);
		vector<int>().swap(array);
	}
	bool chk() {
		int cnt = 0;
		for (int i = 0; i < (int)array.size(); i++)
			if (array[i] == 0)
				cnt++;
		return cnt == (int)array.size() - 1;
	}
	void out() {
		printf("%d\n", op.size());
		for (int i = 0; i < (int)op.size(); i++) 
			printf("%d %d\n", op[i].first, op[i].second);
	}
} tmp;
void bfs() {
	queue<Node> q;
	for (int i = 1; i <= m; i++)
		tmp.array.push_back(a[i]);
	q.push(tmp);
	while (!q.empty()) {
		Node h = q.front();
		q.pop();
		if (h.chk()) {
			h.out();
			
			break;
		}
		for (int i = 0; i < (int)h.array.size(); i++)
			for (int j = i + 1; j < (int)h.array.size(); j++)
				if (h.array[i] >= h.array[j] && h.array[i] != h.array[j] * 2 && i != j && h.array[i] != 0 && h.array[j] != 0) {
					tmp = h;
					tmp.array[i] -= tmp.array[j];
					tmp.array[j] *= 2;
					tmp.op.push_back(make_pair(j + 1, i + 1));
					q.push(tmp);
				}
				else {
					swap(i, j);
					if (h.array[i] >= h.array[j] && h.array[i] != h.array[j] * 2 && i != j && h.array[i] != 0 && h.array[j] != 0) {
						tmp = h;
						tmp.array[i] -= tmp.array[j];
						tmp.array[j] *= 2;
						tmp.op.push_back(make_pair(j + 1, i + 1));
						q.push(tmp);
					}
					swap(i, j);
				}
	}
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m; i++)
		scanf("%d", &a[i]);
	bfs();
	return 0;
}

「ZHYOI-1」游戏

题目链接:「ZHYOI-1」游戏

不会。

「ZHYOI-1」公路翻新

题目链接:「ZHYOI-1」公路翻新

我只会 50 分的方法:首先树剖+线段树区间加和区间最小用来维护边权,对于停工和施工,每次停工村改变时,找到所有的停工村,做一次广搜,知道每个点最近的停工村,这样每次询问就能直接知道最近的停工村。

时间复杂度:\(\text{I don't know}\)

code

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 3e5 + 5;
inline long long read() {
	register long long x = 0, f = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch <= '9' && ch >= '0') {
		x = x * 10 + (ch - '0');
		ch = getchar();
	}
	return x * f;
}
inline void write(long long x) {
	if (x < 0)
		putchar('-'), x = -x;
	if (x > 9)
		write(x / 10);
	putchar(x % 10 + '0');
}
#define int long long
struct Edge {
	int to, val;
};
int n, m;
vector<Edge> e[MAXN];
void init() {
	n = read();
	for (int i = 1, u, v, w; i < n; i++) {
		u = read(), v = read(), w = read();
		e[u].push_back((Edge){v, w});
		e[v].push_back((Edge){u, w});
	}	 
}
int p[MAXN] = {0}, d[MAXN] = {0}, val[MAXN] = {0}, sz[MAXN] = {0}, son[MAXN] = {0};
int top[MAXN] = {0}, id[MAXN] = {0}, rk[MAXN] = {0};
void dfs1(int x, int pr, int depth) {
	p[x] = pr;
	d[x] = depth;
	sz[x] = 1;
	son[x] = -1;
	for (int i = 0; i < (int)e[x].size(); i++) {
		int v = e[x][i].to;
		if (v != pr) {
			dfs1(v, x, d[x] + 1);
			val[v] = e[x][i].val;
			sz[x] += sz[v];
			if (son[x] == -1 || sz[v] > sz[son[x]])
				son[x] = v;
		}
	}
}
int cnt = 0;
void dfs2(int x, int t) {
	top[x] = t;
	id[x] = ++cnt;
	rk[cnt] = x;
	if (son[x] == -1) 
		return;
	dfs2(son[x], t);
	for (int i = 0; i < (int)e[x].size(); i++) {
		int v = e[x][i].to;
		if (v != p[x] && v != son[x]) 
			dfs2(v, v);
	}
}
struct SegTree {
	int mi[MAXN * 4], tag[MAXN * 4];
	#define ls (t << 1)
	#define rs (t << 1 | 1)
	#define mid ((l + r) >> 1)
	void pushup(int t) {
		mi[t] = min(mi[ls], mi[rs]);
	}
	void pushdown(int t) {
		if (tag[t] != 0) {
			mi[ls] += tag[t];
			mi[rs] += tag[t];
			tag[ls] += tag[t];
			tag[rs] += tag[t];
			tag[t] = 0;
		}
	}
	void build(int l, int r, int t) {
		if (l == r) {
			mi[t] = val[rk[l]];
			tag[t] = 0;
			return;
		}
		build(l, mid, ls);
		build(mid + 1, r, rs);
		pushup(t);
	}
	void upd(int L, int R, int l, int r, int t, int x) {
		if (L <= l && r <= R) {
			mi[t] += x;
			tag[t] += x;
			return;
		}
		pushdown(t);
		if (L <= mid)
			upd(L, R, l, mid, ls, x);
		if (mid < R)
			upd(L, R, mid + 1, r, rs, x);
		pushup(t); 
	}
	int qry(int L, int R, int l, int r, int t) {
		if (L <= l && r <= R) 
			return mi[t];
		pushdown(t);
		int ans = 2e9;
		if (L <= mid)
			ans = min(ans, qry(L, R, l, mid, ls));
		if (mid < R)
			ans = min(ans, qry(L, R, mid + 1, r, rs));
		return ans;
	}
} t;
void updtree(int u, int v, int x) {
	while (top[u] != top[v]) {
		if (d[top[u]] < d[top[v]])
			swap(u, v);
		t.upd(id[top[u]], id[u], 1, n, 1, x);
		u = p[top[u]];
	}
	if (d[v] > d[u])swap(u, v);
	if (u != v)
		t.upd(id[v] + 1, id[u], 1, n, 1, x);
}
int st[MAXN] = {0};
bool vis[MAXN] = {false};
void bfs(int u, int v) {
	queue<int> q;
	while (u != v) {
		st[u] = u, st[v] = v;
		if (d[u] > d[v])
			u = p[u];
		else if (d[v] > d[u])
			v = p[v];
		else	
			u = p[u], v = p[v];
	}
	st[u] = u;
	memset(vis, 0, sizeof vis);
	for (int i = 1; i <= n; i++)
		if (st[i] == i)
			q.push(i), vis[i] = true;
	while (!q.empty()) {
		int h = q.front();
		q.pop();
		for (int i = 0; i < (int)e[h].size(); i++) 
			if (!vis[e[h][i].to]) {
				vis[e[h][i].to] = true;
				st[e[h][i].to] = st[h];
				q.push(e[h][i].to);
			}
	}
}
void chk() {
	for (int i = 1; i <= n; i++)
		cout << st[i] << endl;
}
void solve() {
	m = read();
	memset(st, -1, sizeof st);
	for (int i = 1; i <= m; i++) {
		int op, x, y, v;
		op = read();
		if (op == 1) {
			x = read(), v = read();
			write(st[x]), putchar('\n');
			if (st[x] != -1)
				updtree(x, st[x], v);
		}
		else if (op == 2) {
			x = read(), y = read();
			bfs(x, y);
		}
		else {
			x = read();
			if (son[x] == -1)
				putchar('-'), putchar('1'), putchar('\n');
			else
				write(t.qry(id[x] + 1, id[x] + sz[x] - 1, 1, n, 1)), putchar('\n'); 
		}
	}
}

signed main() {
	init();	
	dfs1(1, 1, 1);
	dfs2(1, 1);
	t.build(1, n, 1);
	solve();
	return 0;
}

\[\text{The End} \]

posted @ 2022-08-31 21:12  rlc202204  阅读(23)  评论(0编辑  收藏  举报