Loading

【题解】CF538H Summer Dichotomy

【题解】CF538H Summer Dichotomy

给定若干个区间 \([l_i,r_i]\),将区间分为两组,其中有些区间不能分在一组,使得存在 \((p,q)\) 满足 \(p\) 在第一组所有区间内,\(q\) 在第二组所有区间内,且 \(p+q\in[L,R]\)

我们需要分两组,且一些不能同组,非常像二分图/2-SAT模型。但是直接做非常没有头绪,特别是 \(p+q\in [L,R]\) 的条件。

如果不考虑这个条件,我们可以先贪心求出一组可能的解 \(p = \max\{l_i\},q = \max\{r_i\}\)

如果 \(p \le q\) 显然合法。

如果 \(p>q\),说明存在两个区间 \(l_i \le r_i < l_j \le r_j\),那么 \(p\) 减小就不满足 \(j\)\(q\) 增大就不满足 \(i\)。那么如果 \(p+q < L\),那么就只能增大 \(p\),如果 \(p+q >R\),就只能减小 \(q\)

所以我们可以直接贪心求出最可能的 \((p,q)\),这组 \((p,q)\) 合法是存在解的充要条件。

我们把 \((p,q)\) 带入原区间就可以得到每个区间可以分在 \(1/2\) 组,限制条件可以直接二分图染色判断。

#define N 100005
int L, R, n, m, l[N], r[N], v[N], p, q = inf;
bool flag = true;
vector<int>e[N], c;
void dfs(int x,int col){
	v[x] = col, c.pb(x);
	go(y, e[x]){
		if(v[y])flag &= (v[y] + col) == 3;
		else dfs(y, 3 - col);
	}
}
int main() {
	read(L, R, n, m);
	rp(i, n)read(l[i], r[i]), cmx(p, l[i]), cmn(q, r[i]);
	if(p + q < L)p = L - q;
	else if(p + q > R)q = R - p;
	while(m--){
		int x, y; read(x, y);
		e[x].pb(y), e[y].pb(x);
	}
	rp(i, n)if(!v[i]){
		c.clear(); dfs(i, 1);
		int l1 = 0, r1 = inf, l2 = 0, r2 = inf;
		go(x, c)
			if(1 == v[x])cmx(l1, l[x]), cmn(r1, r[x]);
			else cmx(l2, l[x]), cmn(r2, r[x]);
		if(!flag || l1 > r1 || l2 > r2){puts("IMPOSSIBLE"); return 0;}
		if(l1 <= p && r1 >= p && l2 <= q && r2 >= q)continue;
		if(l2 <= p && r2 >= p && l1 <= q && r1 >= q){
			go(x, c)v[x] = 3 - v[x];
			continue;
		}
		puts("IMPOSSIBLE"); return 0;
	}
	puts("POSSIBLE");
	printf("%d %d\n", p, q);
	rp(i, n)printf("%d", v[i]); el;
	return 0;
}

这题的核心在于贪心找到一个特定解使之代表所有可能的情况。类似与二分是将最优化问题转化为判定,这里是贪心将构造题通过最优化转化为判定。

posted @ 2022-05-11 16:54  7KByte  阅读(31)  评论(0编辑  收藏  举报