1. 程式人生 > 其它 >2022.5.8 AcWing周賽[補]

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;
}