Loading

CF1965F Conference 做题记录

OI 恢复期。link

考虑 Hall 定理,但是这里我们取的点不一定连续。

但是你发现没有更好的办法了,所以此时需要观察并充分利用题目的特点,即利用性质。

发现若 \(l_i = l_j\)\(r_i \le r_j\),那么令 \(l_j \gets l_j + 1\) 其实是等价的。

从大到小枚举左端点,右端点可以双指针。在性质转化之后,不难发现所有的合法区间一定在所有不合法区间前面,直接做就行了。

时间复杂度 \(\mathcal O(n\log n)\)


做一道题目,不能依照以往的套路一就将就,要学会灵活运用,融会贯通。具体表现在观察题目的特殊条件,利用特殊的性质特点来转化题目信息和条件。


点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define fi first
#define se second
#define mkp make_pair
#define pir pair <ll, ll>
#define pb push_back
#define i128 __int128
using namespace std;
char buf[1 << 22], *p1, *p2;
// #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, (1 << 22) - 10, stdin), p1 == p2)? EOF : *p1++)
template <class T>
const inline void rd(T &x) {
	char ch; bool neg = 0;
	while(!isdigit(ch = getchar()))
		if(ch == '-') neg = 1;
	x = ch - '0';
	while(isdigit(ch = getchar()))
		x = (x << 1) + (x << 3) + ch - '0';
	if(neg) x = -x;
}
const ll maxn = 2e5 + 10, inf = 1e18, mod = 1e9 + 7, iv = mod - mod / 2;
ll power(ll a, ll b = mod - 2, ll p = mod) {
	ll s = 1;
	while(b) {
		if(b & 1) s = 1ll * s * a % p;
		a = 1ll * a * a % p, b >>= 1;
	} return s;
}
template <class T, class _T>
const inline ll pls(const T x, const _T y) { return x + y >= mod? x + y - mod : x + y; }
template <class T, class _T>
const inline void add(T &x, const _T y) { x = x + y >= mod? x + y - mod : x + y; }
template <class T, class _T>
const inline void chkmax(T &x, const _T y) { x = x < y? y : x; }
template <class T, class _T>
const inline void chkmin(T &x, const _T y) { x = x < y? x : y; }

ll n, l[maxn], r[maxn], ans[maxn], cnt, bin[maxn];

priority_queue <ll> q;
vector <ll> vec[maxn];

int main() {
	rd(n); cnt = ans[n + 1] = 0;
	for(ll i = 1; i <= n; i++)
		rd(l[i]), rd(r[i]), vec[l[i]].pb(r[i]);
	for(ll i = 1; i <= 2e5; i++) {
		ans[i] = bin[i] = 0;
		for(ll j: vec[i]) q.push(-j);
		l[i] = i, vec[i].clear();
		while(!q.empty() && -q.top() < i) q.pop();
		if(q.empty()) r[i] = i - 1;
		else r[i] = -q.top(), q.pop();
	}
	for(ll i = 1; i <= 2e5; i++)
		if(l[i] <= r[i]) vec[r[i]].pb(i);
	for(ll i = 2e5, j = 2e5; i; i--) {
		for(ll k: vec[i]) ++bin[l[k]], ++cnt;
		vec[i].clear();
		while(cnt < j - i + 1) cnt -= bin[j--];
		++ans[j - i + 1];
	}
	for(ll i = n; i; i--) ans[i] += ans[i + 1];
	for(ll i = 1; i <= n; i++) printf("%d\n", ans[i]);
	return 0;
}
posted @ 2025-03-17 22:08  Sktn0089  阅读(13)  评论(0)    收藏  举报