2022.5.8 AcWing周赛[补]

A 暴力

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10;

int n;
int st[N];

int main() {
	scanf("%d", &n);
	for (int i = 1; i < n; i++) {
		int tmp;
		scanf("%d", &tmp);
		st[tmp] = 1;
	}

	int ans = 0;
	for (int i = 1; i <= n; i++) {
		if (!st[i])
			printf("%d\n", i);
	}

	return 0;
}

B 思维题

题干看起来唬人,其实就是求两个区间集合分别的左端点和右端点的最大值和最小值,做两个差求max。

#include <bits/stdc++.h>
using namespace std;

typedef pair<int, int> PII;

const int N = 2e5 + 10, INF = 1e9 + 7;
PII st1[N], st2[N];
int n, m;
int minx_1 = INF, minx_2 = INF, miny_1 = INF, miny_2 = INF;
int maxx_1 = -INF, maxx_2 = -INF, maxy_1 = -INF, maxy_2 = -INF;

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d %d", &st1[i].first, &st1[i].second);
		minx_1 = min(minx_1, st1[i].first);
		maxx_1 = max(maxx_1, st1[i].first);
		miny_1 = min(miny_1, st1[i].second);
		maxy_1 = max(maxy_1, st1[i].second);
	}

	scanf("%d", &m);
	for (int i = 1; i <= m; i++) {
		scanf("%d %d", &st2[i].first, &st2[i].second);
		minx_2 = min(minx_2, st2[i].first);
		maxx_2 = max(maxx_2, st2[i].first);
		miny_2 = min(miny_2, st2[i].second);
		maxy_2 = max(maxy_2, st2[i].second);
	}

	int ans1 = maxx_1 - miny_2;
	int ans2 = maxx_2 - miny_1;

	int ans = max(ans1, ans2);

	if (ans <= 0) {
		printf("0\n");
	} else {
		printf("%d\n", ans);
	}

	return 0;
}

C 线性DP

对于初始值的赋值,一定要注意! 对于不符合题意的情况,一定要在更新的过程中处理,使得后面迭代的时候不会基于这种情况继续拓展。

#include <bits/stdc++.h>
using namespace std;

const int N = 210;

typedef long long LL;

// 前 i 个中, 选取 第i个,且选了z个的最大值,
LL f[N][N];
int n, k, x;
LL a[N];

/*
动态规划,问题在于我的初始化,把所有内容初始化为0。
y总是先初始化为 -INF,然后 0,0 位置为0.

区别就在这。

必须让“不符合条件的情况”不能被后面的选到

比如,

62 5 26
348066485 57655106 90557094 189353657 393149030
90669845 749562291 444692939 154911374 647203009
464057830 337945632 62283158 398711662 224351634
547516379 820527196 532393946 561114811 344613363
898316463 371263191 641162655 343937716 393059796
206646730 133740842 154853950 712270084 8202542
21688704 458218245 340343275 563630863 23425655
852558927 576952619 774367632 653143066 60356793
805318359 271736677 74855207 941146803 401632504
691058777 705264018 690114815 333531660 933524426
765335296 315930422 327077761 623489832 841610573
839047747 441249855 619568762 355699462 276462309
953792795 965380312

当枚举到第六个的时候, f[6][1] 一定要是很大的负数,
因为 只取第六个已经不符合题意了,所以,像赋初值为0;
更新时,直接让f[i][1] = a[i],这几种写法都是有问题的。

*/

int main() {
	scanf("%d %d %d", &n, &k, &x);
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &a[i]);
	}

	memset(f, -0x3f, sizeof f);
	f[0][0] = 0;

	if (x * k + k - 1 < n) {
		printf("-1\n");
		return 0;
	} else {

		for (int i = 1; i <= n; i++) {
			for (int z = 1; z <= min(x, i); z++) {
				//cout << i << " " << z << endl;
				for (int j = max(0, i - k); j <= max(1, i - 1); j++) {
					// 不会更新到 0 这一列,所以都是 -INF
					// 但是,因为前面k个能接触到 f[0][0]
					// 所以,符合题意,也是能正常取 f[i][1] = a[i]的
					f[i][z] = max(f[i][z], f[j][z - 1] + a[i]);
				}
			}
		}

		LL ans = 0;
		for (int i = n - k + 1; i <= n; i++) {
			ans = max(ans, f[i][x]);
		}
		printf("%lld\n", ans);

	}

	return 0;
}
posted @ 2022-05-08 12:17  superPG  阅读(22)  评论(0编辑  收藏  举报