其他分享
首页 > 其他分享> > Codeforces Round #812 (Div. 2)

Codeforces Round #812 (Div. 2)

作者:互联网

A

这竟然是我场上唯一一道没1A的题,蚌。

注意初值问题。

#include <cstdio>
#include <algorithm>
#include <cstring>

inline int min(const int x, const int y) {return x < y ? x : y;}
inline int max(const int x, const int y) {return x > y ? x : y;}

int a[10];

int main() {
	int _;
	scanf("%d", &_);
	while (_ --) {
		int n, mxx = 0, mnx = 0, mxy = 0, mny = 0;
		scanf("%d", &n);
		for (int i = 1; i <= n; ++ i) {
			int x, y;
			scanf("%d%d", &x, &y);
			mxx = max(mxx, x), mnx = min(mnx, x), mxy = max(mxy, y), mny = min(mny, y);
		}
		printf("%d\n", max(0, mxy - mny) * 2 + max(0, mxx - mnx) * 2);
	}
	return 0;
}

B

和某年普及组铺设道路一样。

更简单的方法是,显然如果序列不是单峰的就是 NO,否则 YES。

#include <cstdio>
#include <algorithm>
#include <cstring>

inline int min(const int x, const int y) {return x < y ? x : y;}
inline int max(const int x, const int y) {return x > y ? x : y;}

int a[100005];

int main() {
	int _;
	scanf("%d", &_);
	while (_ --) {
		int n, mx = 0;
		long long ans = 0;
		scanf("%d", &n);
		for (int i = 1; i <= n; ++ i) scanf("%d", a + i), mx = max(mx, a[i]);
		for (int i = 2; i <= n; ++ i) if (a[i] > a[i - 1]) ans += a[i] - a[i - 1];
		if (ans + a[1] <= mx) puts("YES");
		else puts("NO");
	}
	return 0;
}

C

考虑一个 \(k\),构造出 \(n-1...k^2-n+1\)。

每次找到最大的 \(k\) 即可。

记得截至写完这道题我的排名还是垫底

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

inline int min(const int x, const int y) {return x < y ? x : y;}
inline int max(const int x, const int y) {return x > y ? x : y;}

int a[100005];
void solve(int n) {
	if (n == 0) return;
	int k = sqrt(2 * n - 2 + 0.5);
	solve(k * k - (n - 1));
	for (int i = n - 1; i >= k * k - (n - 1); -- i) printf("%d ", i);
}

int main() {
	int _;
	scanf("%d", &_);
	while (_ --) {
		int n;
		scanf("%d", &n);
		solve(n);
		puts("");
	}
	return 0;
}

D

如果每一层都去问,那么整个询问过程就是一颗二叉树,太慢了。

由于交互次数上限和暴力次数只差一个常数,所以考虑乱搞出 \(k\) 叉树式的询问方式。

如果像四叉树那样询问,那么对于四个人 \(a,b,c,d\),\(a\) 要和 \(b\) 打,\(c\) 要和 \(d\) 打,两边的胜者还要打,我们的目标就是两次问出 \(a,b,c,d\) 中的胜者。

分类讨论一下不难发现确实只需要两次。首先询问 \(a,c\) 谁赢了。

  1. 平局。胜者在 \(b,d\) 中。
  2. \(a\) 获胜。胜者在 \(a,d\) 中。
  3. \(c\) 获胜。胜者在 \(b,c\) 中。

注意当 \(n\) 为奇数时要特判,否则询问次数会超限。

第一次做交互题竟然一遍过了

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>

inline int min(const int x, const int y) {return x < y ? x : y;}
inline int max(const int x, const int y) {return x > y ? x : y;}
int check(int a, int b) {
	printf("? %d %d\n", a, b);
	fflush(stdout);
	int x;
	scanf("%d", &x);
	return x;
}
int solve(int l, int r) {
	if (l == r) return l;
	int mid = l + r >> 1;
	int lmid = l + mid >> 1, rmid = mid + 1 + r >> 1;
	int a = solve(l, lmid), b = solve(lmid + 1, mid), c = solve(mid + 1, rmid), d = solve(rmid + 1, r);
	int tmp = check(a, c);
	if (tmp == 0) {
		if (check(b, d) == 1) return b;
		else return d;
	} else if (tmp == 1) {
		if (check(a, d) == 1) return a;
		else return d;
	} else {
		if (check(c, b) == 1) return c;
		else return b;
	}
}

int main() {
	int _;
	scanf("%d", &_);
	while (_ --) {
		int n;
		scanf("%d", &n);
		if (n & 1) {
			int a = solve(1, 1 << n - 1), b = solve((1 << n - 1) + 1, 1 << n);
			if (check(a, b) == 1) printf("! %d\n", a), fflush(stdout);
			else printf("! %d\n", b), fflush(stdout);
		} else printf("! %d\n", solve(1, 1 << n)), fflush(stdout);
	}
	return 0;
}

E

不难发现 \(a_{i,j}\) 位置可以与 \(a_{j,i}\) 交换。

从前往后考虑每个格子,如果 \(a_{i,j} < a_{j,i}\),那么第 \(k=i\) 的操作和 \(k=j\) 的操作要么同时执行要么同时不执行。反之有且仅有一个执行。

这玩意儿维护的方法多了去了,并查集,dfs……

官方给的是一个比较简洁并查集的维护方式。

所以我为什么过了D就摆烂,要是把这题切了岂不上大分

#include <cstdio>
#include <numeric>
#include <algorithm>

int a[1005][1005], fa[2005];
int find(int x) {
	if (x < 0) return -find(-x);
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}
inline void merge(int u, int v) {
	u = find(u), v = find(v);
	if (u != v && u != -v) u > 0 ? fa[u] = v : fa[-u] = -v;
}

int main() {
	int _;
	scanf("%d", &_);
	while (_ --) {
		int n;
		scanf("%d", &n);
		for (int i = 1; i <= n; ++ i)
			for (int j = 1; j <= n; ++ j) scanf("%d", &a[i][j]);
		std::iota(fa + 1, fa + 2 * n + 1, 1);
		for (int i = 1; i <= n; ++ i)
		for (int j = 1; j <= n; ++ j)
			if (a[i][j] < a[j][i]) merge(i, j);
			else if (a[i][j] > a[j][i]) merge(i, -j);
		for (int i = 1; i <= n; ++ i) if (find(i) > 0)
			for (int j = 1; j <= n; ++ j) std::swap(a[i][j], a[j][i]);
		for (int i = 1; i <= n; ++ i, puts(""))
		for (int j = 1; j <= n; ++ j) printf("%d ", a[i][j]);
	}
	return 0;
}

标签:return,int,scanf,Codeforces,solve,const,812,include,Div
来源: https://www.cnblogs.com/stinger/p/16558929.html