【第29次CSS CSP】202303 (C++)

本文展示了不同解题方法在处理编程问题中的应用,从最初的暴力模拟到使用优先队列优化,再到通过排序和前缀和减少计算量,最后采用二分查找进一步提升效率。每个案例都提供了相应的代码示例,展示了解题思路的演进过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

202303-1

 

解题思路:题目说任意两块的交集面积均为 0,所以不需要去重,直接暴力模拟就行了

参考代码O(Kn)

#include <bits/stdc++.h>
using namespace std;
int n, a, b;
int g[1005][1005];
int ans;
int main() {
	cin >> n >> a >> b;
	int x1, y1, x2, y2;
	for (int i = 1; i <= n; i++) {
		cin >> x1 >> y1 >> x2 >> y2;
		int x = min(a, x2) - max(0, x1);
		int y = min(b, y2) - max(0, y1);
		if (x >= 0 && y >= 0) ans += x * y;
	}

	cout << ans;
	return 0;
}

 

202303-2

 

解题思路:一开始想着用堆一次一个操作,果然超时了

参考代码(70分)O(Klog n)(常数太太大了)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m, k;
struct node {
	int t, c;
	friend bool operator < (node a, node b) {
		return a.t < b.t;
	}
};
priority_queue<node>q;
int main() {
	cin >> n >> m >> k;
	int t, c;
	for (int i = 1; i <= n; i++) {
		cin >> t >> c;
		q.push({t, c});
	}
	while (m - q.top().c >= 0 && q.top().t >= k) {
		node now = q.top();
		q.pop();
		now.t--;
		m -= now.c;
		q.push(now);
	}
	cout << q.top().t;
	return 0;
}

解题思路.改:先按时间从大到小排序,这样每次操作一个区间,并用前缀和优化,勉强AC

参考代码 最坏O(n^2),但是勉强过了

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m, k;
struct node {
	int t, c;
} a[N];
int s[N];
bool cmp(node a, node b) {
	if (a.t == b.t) {
		return a.c < b.c;
	}
	return a.t > b.t;
}
int main() {
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++) cin >> a[i].t >> a[i].c;
	sort(a + 1, a + n + 1, cmp);
	for (int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i].c;
	int cnt, res;
	while (m >= 0 && a[1].t > k) {
		cnt = n;
		for (int i = 2; i <= n; i++) {
			if (a[i].t != a[i - 1].t) {
				cnt = i - 1;
				break;
			}
		}
		res = s[cnt];
		if (m - res >= 0) {
			m -= res;
			for (int i = 1; i <= cnt; i++) a[i].t--;
		} else break;
	}
	cout << a[1].t;
	return 0;
}

解题思路.新:发现答案是有连续性的,直接二分答案,快了不少

参考代码 O(nlog n)

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m, k;
struct node {
	int t, c;
} a[N];
bool check(int x) {
	int res = 0;
	for (int i = 1; i <= n; i++) {
		if (a[i].t > x) {
			res += a[i].c * (a[i].t - x);
		}
	}
	if (m - res >= 0) return 1;
	else return 0;
}
int find() {
	int l = k, r = N;
	while (l <= r) {
		int mid = (l + r) >> 1;
		if (check(mid)) r = mid - 1;
		else l = mid + 1;
	}
	return l;
}
int main() {
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i++) cin >> a[i].t >> a[i].c;
	cout << find();
	return 0;
}

 

202303-3

解题思路:

参考代码

202303-4

解题思路:

参考代码

202303-5

解题思路:

参考代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值