1. 程式人生 > 其它 >10.24訓練賽

10.24訓練賽

這次我們A水題的速度非常快, 大概1個多小時作業, A了7道題, (zsyA掉了莫比烏斯%%%), 但後面竟然一道題也沒想出來, 非常不應該。。


H. Haunted House
當時看到這道題的時候確實想了很長時間, 也有了一些思路, 但以為是個高階的資料結構, 就沒有寫出來。 還是直接說正解把, 首先, 每個人至多被一個鬼嚇住, 而一個鬼可以嚇住多個人, 所以我們去找每個人會被那個鬼嚇住, 不如去找每個鬼能嚇住多少人, 那麼這個就比較容易一點了, 因為每個鬼活躍的時間都是固定的, 如果抓到人, 更新鬼的活躍時間就行了, 人直接淘汰掉, 而列舉人的話總不能把鬼淘汰了把, set可以解決, 至於複雜度的話, 假如一個鬼活躍時間為x, 總時間為T, 那活躍的時間段的個數是\(T/x\)

,由於每個鬼活躍的時間是個排列(x <= n),總時間就是\(Tlogm\), 在加上set\(logn\)的複雜度, 總時間複雜度為\((Tlogmlogn)\)
這道題還讓我複習了一下set的用法, 不失為一道好題
(注:部分內容借鑑gcf部落格)

點選檢視程式碼
#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

template < typename T > inline void read(T &x) {
	x = 0; T ff = 1, ch = getchar();
	while (!isdigit(ch)) {
		if (ch == '-') ff = -1;
		ch = getchar();
	}
	while (isdigit(ch)) {
		x = (x << 1) + (x << 3) + (ch ^ 48);
		ch = getchar();
	}
	x *= ff;
} 

int n, m, p[N];
set < pair < int, int > > s;
pair < int, int > ans[N];

int main() {
	read(n), read(m);
	for (int i = 0; i < n; ++i) read(p[i]);
	for (int i = 0; i < m; ++i) {
		int x; read(x);
		s.insert({x, i});
	}
	for (int i = 0; i < n; ++i) {
		int cnt = 0;
		while (true) {
			set < pair < int, int > > ::iterator it = s.lower_bound({cnt - i, -1});
			if (it == s.end()) break;
			pair < int, int > x = *it;
			if (x.first <= cnt - i + p[i] - 1) {
				s.erase(it);
				ans[x.second].first = i;
				ans[x.second].second = x.first + i;
				cnt = x.first + p[i] + i + 1; 
			} else cnt += 2 * p[i];
		}
	}
	for (set < pair < int, int > > ::iterator it = s.begin(); it != s.end(); ++it) {
		pair < int, int > x = *it;
		ans[x.second].first = ans[x.second].second = -1;
	}
	for (int i = 0; i < m; ++i) 
		printf("%d %d\n", ans[i].first, ans[i].second);
	return 0;
}