P7913 [CSP-S 2021] 廊桥分配

Solution

更新一下,之前写的太烂了。

首先我们能想到一个暴力算法,就是枚举分配到国内区和国外区的廊桥个数,然后用两个优先队列来模拟,复杂度 \(\mathcal {O}(n^2 \log n)\)

预计得分: 40

然后我们考虑,当一个区的廊桥数确定为 \(x\) 的时候,另一个廊桥数是 \(n - x\)

当一个区的廊桥数增加的时候,他能停靠的飞机只增不减。

如果我们给廊桥标上号,当增加廊桥数目之后,之前停靠在廊桥上的飞机不会停到新增加的廊桥上。

如果每一遍都模拟,复杂度过高,当一个区为 \(x + 1\) 个廊桥时,我们可以利用有 \(x\) 个廊桥的结果算出 \(x + 1\) 的结果。

\(res1_i\) 表示在国内区前 \(i\) 个廊桥能停靠的飞机个数,\(res2_i\) 表示在国际区前 \(i\) 个廊桥能停靠的飞机个数。

我们可以通过前缀和来实现这个数组的求出,也就是求出每个廊桥可以停靠的飞机个数,我们可以维护两个优先队列,一个是空闲的廊桥,一个是要离开的飞机所停靠的廊桥。

这个过程的话,用什么数据结构维护一下就行了。

但是个人觉得 set 最简洁。

复杂度 \(\mathcal {O} (n \log n)\), 预计得分 \(100\)


/*
	Work by: TLE_Automation
*/
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define int long long
using namespace std;

const int N = 1e6 + 10;
const int MAXN = 2e5 + 10;

inline char readchar() {
	static char buf[100000], *p1 = buf, *p2 = buf;
	return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}

inline int read() {
#define readchar getchar
	int res = 0, f = 0;char ch = readchar();
	for(; !isdigit(ch); ch = readchar()) if(ch == '-') f = 1;
	for(; isdigit(ch); ch = readchar()) res = (res << 1) + (res << 3) + (ch ^ '0');
	return f ? -res : res;
}

inline void print(int x) {
	if (x < 0 ) putchar('-'), x = -x;
	if (x > 9 ) print(x / 10);
	putchar(x % 10 + '0');
}

typedef pair <int, int> p;

struct Node {
	int st, ed; 
	bool operator < (const Node &x) const {
		return st < x.st;
	}
}a[MAXN], b[MAXN];

int res1[MAXN], res2[MAXN], ans = 0;
priority_queue <p, vector <p>, greater <p> > q1;
priority_queue <int, vector <int>, greater <int> > q2;

signed main() {
	int n = read(), m1 = read(), m2 = read();
	for(int i = 1; i <= m1; i++) a[i].st = read(), a[i].ed = read();
	for(int i = 1; i <= m2; i++) b[i].st = read(), b[i].ed = read();
	sort(a + 1, a + m1 + 1), sort(b + 1, b + m2 + 1);
	for(int i = 1; i <= n; i++) q2.push(i);
	for(int i = 1; i <= m1; i++) {
		while(!q1.empty() && a[i].st >= q1.top().first) q2.push(q1.top().second), q1.pop();
		if(q2.empty()) continue;
		int wz = q2.top(); q2.pop();
		res1[wz]++; q1.push(make_pair (a[i].ed, wz));
	}
	while(!q1.empty()) q1.pop();
	while(!q2.empty()) q2.pop();
	for(int i = 1; i <= n; i++) q2.push(i);
	for(int i = 1; i <= m2; i++) {
		while(!q1.empty() && b[i].st >= q1.top().first) q2.push(q1.top().second), q1.pop();
		if(q2.empty()) continue;
		int wz = q2.top(); q2.pop();
		res2[wz]++; q1.push(make_pair (b[i].ed, wz));
	}
	for(int i = 1; i <= n; i++) res1[i] += res1[i - 1], res2[i] += res2[i - 1];
	for(int i = 0; i <= n; i++) 
		ans = max(ans, res1[i] + res2[n - i]);
	cout << ans;
}

set 做法:

#include<bits/stdc++.h>
using namespace std;
const int Maxn = 1e5 + 10;
int n, m1, m2, res1[Maxn], res2[Maxn], Maxx = 0;
std::set <std::pair <int, int> > qwq, qaq;

void Work(std::set <std::pair<int, int> > s, int res[] ) {
	for(int i = 1; i <= n; i++) {
		int pos = 0, ans = 0;
		for(auto it = s.begin(); it != s.end(); it = s.lower_bound(make_pair(pos, 0))) {
			ans++, pos = it -> second, s.erase(it);
		}
		res[i] = res[i - 1] + ans; 
	}
}

int main() {
	scanf("%d %d %d", &n, &m1, &m2);
	for(int i = 1, l, r; i <= m1; i++)
		scanf("%d %d", &l, &r), qwq.insert(make_pair(l, r));	
	for(int i = 1, l, r; i <= m2; i++) 
		scanf("%d %d", &l, &r), qaq.insert(make_pair(l, r));
	Work(qwq, res1), Work(qaq, res2);	
	for(int i = 0; i <= n; i++) Maxx = std::max(Maxx, res1[i] + res2[n - i]);
	return !printf("%d\n", Maxx);
}
posted @ 2022-06-14 09:10  TLE_Automation  阅读(519)  评论(0)    收藏  举报