ABC 256 C-D

我又双叒叕回来啦!

本场RP = INT_MAX。

C

看上去也没什么巧妙解法,于是决定直接暴力。
然后算了下时间复杂度,$ O(n^9) $的复杂度撑不住呀!
然后……
image
想了下,发现其实枚举左上4个格子就够了,时间复杂度 $ O(n^4) $,其中 $ n = max(h_1, h_2, h_3, w_1, w_2, w_3) $,可以通过。
暴力万岁

#include <iostream>
#include <string>
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <set>
#include <map>
#include <utility>
#include <queue>
#include <vector>
#include <bitset>
#include <stack>
#include <sstream>
#include <algorithm>

using namespace std;

int main() {
	int h1, h2, h3, w1, w2, w3;
	scanf("%d %d %d %d %d %d", &h1, &h2, &h3, &w1, &w2, &w3);
	int a11, a12, a13, a21, a22, a23, a31, a32, a33;
	int ans = 0;
	for (a11 = 1; a11 < h1 - 1 && a11 < w1 - 1; a11++) {
		for (a12 = 1; a11 + a12 < h1; a12++) {
			for (a21 = 1; a11 + a21 < w1; a21++) {
				for (a22 = 1; a21 + a22 < h2 && a12 + a22 < w2; a22++) {
					a13 = h1 - a11 - a12;
					a23 = h2 - a21 - a22;
					a31 = w1 - a11 - a21;
					a32 = w2 - a12 - a22;
					if (h3 - a31 - a32 == w3 - a13 - a23 && h3 - a31 - a32 > 0) {
						ans++;
					}
				}
			}
		}
	}
	printf("%d", ans);
	return 0;
}

D

解法一:前缀和

我们把这些区间内的元素看做1,其余的看做0,那么本题就成了找连续的1。
但是有个问题:直接赋值会超时。
我们用前缀和来优化:左边+1,右边-1。
这样中间的就都为1了。


前缀和有个特点,就是他会累加前面的。
所以,1 0 0 0 0 0 -1 0 0 会变成 1 1 1 1 1 1 0 0 0。
然后多个1 0跑一边就能全部带走,所以就不会超时了。
时间复杂度: $ O(n) $

#include <iostream>
#include <string>
#include <cmath>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <set>
#include <map>
#include <utility>
#include <queue>
#include <vector>
#include <bitset>
#include <stack>
#include <sstream>
#include <algorithm>

using namespace std;

#define maxn 200005

int prefix[maxn];

int main() {
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		int l, r;
		scanf("%d %d", &l, &r);
		prefix[l]++;
		prefix[r]--;
	}
	for (int i = 1; i < maxn; i++) {
		prefix[i] += prefix[i - 1];
	}
	int ansl, ansr;
	bool flag = false;
	for (int i = 0; i < maxn; i++) {
		if (prefix[i] && !flag) {
			flag = true;
			ansl = i;
		}
		if (!prefix[i] && flag) {
			flag = false;
			ansr = i;
			printf("%d %d\n", ansl, ansr);
		}
	}
	return 0;
}

解法二:直接模拟

先把区间存到pair里,然后排一下序。
遍历的时候,如果这个区间和上一个合并过的区间有交点的话,那就更新一下右端点。
如:[10, 13) 和 [12, 48)有交点(12),但[8, 67)和[122, 514)没有交点。
由于博主懒,这里就先不贴代码了。

posted @ 2022-06-19 22:04  A-Problem-Solver  阅读(29)  评论(0编辑  收藏  举报