P7562 [JOISC 2021] イベント巡り 2 (Event Hopping 2) (Day4)

Sol

直接一位一位贪,判断贪完之后是否能放满 \(k\) 个即可。

这个东西我们只需要维护一个区间里面最多能取几个,然后 set 维护当前没选的段即可。

Code

#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define pf push_front
#define desktop "C:\\Users\\incra\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
	if (y > x) return x = y,true;
	return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
	if (y < x) return x = y,true;
	return false;
}
LL power (LL a,LL b,LL p) {
	LL ans = 1;
	while (b) {
		if (b & 1) ans = ans * a % p;
		a = a * a % p;
		b >>= 1;
	}
	return ans;
}
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << (s) << endl
const int N = 200010,MAX_LOG = 20;
int n,k;
int l[N],r[N];
int f[N][MAX_LOG];
int query (int l,int r) {
	if (l > r) return 0;
	int ans = 0;
	int p = l;
	for (int i = MAX_LOG - 1;i >= 0;i--) {
		if (f[p][i] <= r) {
			p = f[p][i] + 1;
			ans += 1 << i;
		}
	}
	return ans;
}
void mian () {
	cin >> n >> k;
	vector <double> all;
	for (int i = 1;i <= n;i++) cin >> l[i] >> r[i],all.pb (l[i] + 0.1),all.pb (r[i] - 0.1);
	sort (all.begin (),all.end ());
	all.erase (unique (all.begin (),all.end ()),all.end ());
	int m = all.size ();
	auto find = [&](double x) {
		return lower_bound (all.begin (),all.end (),x) - all.begin () + 1;
	};
	memset (f,0x3f,sizeof (f));
	for (int i = 1;i <= n;i++) l[i] = find (l[i] + 0.1),r[i] = find (r[i] - 0.1),tomin (f[l[i]][0],r[i]);
	for (int i = m;i >= 1;i--) tomin (f[i][0],f[i + 1][0]);
	for (int j = 1;j < MAX_LOG;j++) {
		for (int i = 1;i <= m;i++) {
			if (f[i][j - 1] <= m) tomin (f[i][j],f[f[i][j - 1] + 1][j - 1]);
		}
	}
	if (query (1,m) < k) {
		puts ("-1");
		return ;
	}
	set <PII> s;
	s.insert ({1,m});
	vector <int> ans;
	int tmp = query (1,m);
	for (int i = 1;i <= n;i++) {
		if (ans.size () == k) break;
		if (s.begin () -> x > l[i]) continue;
		auto it = --s.upper_bound ({l[i],(int)1e9});
		// cout << i << ' ' << l[i] << ' ' << r[i] << "     " << it -> x << ' ' << it -> y << "     " << next (it) -> x << ' ' << next (it) -> y << endl;
		if (it -> x <= l[i] && r[i] <= it -> y) {
			int ntmp = tmp - query (it -> x,it -> y) + query (it -> x,l[i] - 1) + query (r[i] + 1,it -> y) + 1;
			if (ntmp >= k) {
				tmp = ntmp;
				ans.pb (i);
				auto _ = *it;
				s.erase (it);
				if (_.x <= l[i] - 1) s.insert ({_.x,l[i] - 1});
				if (r[i] + 1 <= _.y) s.insert ({r[i] + 1,_.y});
			}
		}
	}
	for (int x : ans) cout << x << endl;
}
int main () {
	int T = 1;
	// cin >> T;
	while (T--) mian ();
	return 0;
}
posted @ 2025-05-02 10:02  incra  阅读(11)  评论(0)    收藏  举报