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,构造出 n1...k2n+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,da 要和 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

不难发现 ai,j 位置可以与 aj,i 交换。

从前往后考虑每个格子,如果 ai,j<aj,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;
}

本文作者:zqs2020

本文链接:https://www.cnblogs.com/stinger/p/16558929.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   zqs2020  阅读(97)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.