ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces 309E - Sheep(二分+贪心)

2022-02-10 01:31:13  阅读:185  来源: 互联网

标签:Sheep 309E int void Codeforces mid 区间 print define


Codeforces 题面传送门 & 洛谷题面传送门

为啥感觉这种跟区间有关的贪心我都不太会做啊/dk

考虑二分答案 \(mid\)​,任务转化为检验是否存在一个排列满足对于序列中任意两个相交的区间,它们在排列中的距离都 \(\le mid\),并顺带找出一个符合要求的排列。

我们考虑一个贪心的策略:按位置从小到大钦定所有区间的位置。对每个区间维护一下这一区间最远可以放在那里,设为 \(p_i\),也就是说这一区间在序列中的位置必须 \(\le p_i\),那么假设当前钦定了前 \(j\) 个位置上的值,我们开一个桶 \(buc_c\) 维护有多少个 \(p_i=c\) 并统计 \(buc\) 的前缀和 \(sumbuc\),显然根据 Hall 定理,如果存在一个 \(k>j\) 满足 \(sumbuc_k>k-j\),就无解,否则我们求出 \(sumbuc_k=k-j\) 且最小的 \(k\),那么显然我们在第 \(j+1\) 步放置的区间 \(i\) 必须满足 \(p_i\le k\)——否则下一步就不符合 \(sumbuc\) 的要求了,而我们又尽量希望这个区间尽量不与其他区间相交,因此我们要求该区间右端点尽可能小,也就是说找出 \(p_i\le k\) 且 \(r_i\) 最小的区间放在 \(j+1\),然后更新其他区间的 \(p\) 即可。感性理解一下可知该算法正确性。

时间复杂度 \(n^2\log n\)。

#include <bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/hash_policy.hpp>
using namespace std;
//using namespace __gnu_pbds;
#define fi first
#define se second
#define fill0(a) memset(a, 0, sizeof(a))
#define fill1(a) memset(a, -1, sizeof(a))
#define fillbig(a) memset(a, 63, sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
#define mt make_tuple
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
template <typename T1, typename T2> void chkmin(T1 &x, T2 y){
	if (x > y) x = y;
}
template <typename T1, typename T2> void chkmax(T1 &x, T2 y){
	if (x < y) x = y;
}
typedef pair<int, int> pii;
typedef long long ll;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef long double ld;
namespace fastio {
	#define FILE_SIZE 1 << 23
	char rbuf[FILE_SIZE], *p1 = rbuf, *p2 = rbuf, wbuf[FILE_SIZE], *p3 = wbuf;
	inline char getc() {
		return p1 == p2 && (p2 = (p1 = rbuf) + fread(rbuf, 1, FILE_SIZE, stdin), p1 == p2) ? -1: *p1++;
	}
	inline void putc(char x) {(*p3++ = x);}
	template <typename T> void read(T &x) {
		x = 0; char c = getc(); T neg = 0;
		while (!isdigit(c)) neg |= !(c ^ '-'), c = getc();
		while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getc();
		if (neg) x = (~x) + 1;
	}
	template <typename T> void recursive_print(T x) {
		if (!x) return;
		recursive_print (x / 10);
		putc (x % 10 ^ 48);
	}
	template <typename T> void print(T x) {
		if (!x) putc('0');
		if (x < 0) putc('-'), x = -x;
		recursive_print(x);
	}
	template <typename T> void print(T x,char c) {print(x); putc(c);}
	void readstr(char *s) {
		char c = getc();
		while (c <= 32 || c >= 127) c = getc();
		while (c > 32 && c < 127) s[0] = c, s++, c = getc();
		(*s) = 0;
	}
	void printstr(string s) {
		for (int i = 0; i < s.size(); i++) putc(s[i]);
	}
	void printstr(char *s) {
		int len = strlen(s);
		for (int i = 0; i < len; i++) putc(s[i]);
	}
	void print_final() {fwrite(wbuf, 1, p3 - wbuf, stdout);}
}
const int MAXN = 2000;
const int INF = 0x3f3f3f3f;
int n, ans[MAXN + 5], l[MAXN + 5], r[MAXN + 5], pos[MAXN + 5], vis[MAXN + 5];
bool check(int mid) {
	memset(vis, 0, sizeof(vis));
	for (int i = 1; i <= n; i++) pos[i] = n;
	for (int i = 1; i <= n; i++) {
		static int buc[MAXN + 5]; memset(buc, 0, sizeof(buc));
		for (int j = 1; j <= n; j++) if (!vis[j]) buc[pos[j]]++;
		for (int j = 1; j <= n; j++) buc[j] += buc[j - 1];
		for (int j = 1; j <= n; j++) if (buc[j] > max(j - i + 1, 0)) return 0;
		int nw = 0, nd_lim = n;
		for (int j = n; j >= i; j--) if (buc[j] == j - i + 1) nd_lim = j;
		for (int j = 1; j <= n; j++) if (!vis[j] && r[j] < r[nw] && pos[j] <= nd_lim) nw = j;
		ans[i] = nw; vis[nw] = 1;
//		printf("! %d\n", nw);
		for (int j = 1; j <= n; j++) if (!vis[j] && max(l[j], l[nw]) <= min(r[j], r[nw]))
			chkmin(pos[j], i + mid);
//		for (int j = 1; j <= n; j++) printf("%d%c", pos[j], " \n"[j == n]);
//		for (int j = 1; j <= n; j++) printf("%d%c", vis[j], " \n"[j == n]);
	}
	return 1;
}
int main() {
	scanf("%d", &n); r[0] = INF;
	for (int i = 1; i <= n; i++) scanf("%d%d", &l[i], &r[i]);
	int L = 0, R = n - 1, p = 0;
//	check(1);
	while (L <= R) {
		int mid = L + R >> 1;
		if (check(mid)) p = mid, R = mid - 1;
		else L = mid + 1;
	}
//	printf("%d\n", p);
	check(p);
	for (int i = 1; i <= n; i++) printf("%d%c", ans[i], " \n"[i == n]);
	return 0;
}

标签:Sheep,309E,int,void,Codeforces,mid,区间,print,define
来源: https://www.cnblogs.com/ET2006/p/Codeforces-309E.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有