Codeforces 1175E 倍增

Posted pkgunboat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 1175E 倍增相关的知识,希望对你有一定的参考价值。

题意:给你n个区间和m次询问,每次询问一个区间[l, r]至少需要几个区间覆盖?

思路:如果只有一个区间,并且区间是整个取值范围的话,这是一个经典的区间覆盖问题,我们都知道贪心可以解决。现在我们需要快速知道对于一个指定区间至少需要多少个区间来覆盖。我们有一个初步想法,我们可以预处理出包含某一个点的区间中最大的右端点,这样就可以贪心的解决一个区间的问题了。但是,这种做法肯定可以被卡掉,所以我们用倍增来优化这个过程,设st[i][j]是从i位置走连续的2 ^ j个区间可以到的最右端的位置,正常的倍增处理即可。需要注意,如果左半边的区间已经不连续了,则置成-1。然后用试填法。有一个剪枝,我们读入一个区间,先判断左端点走最大的步数(2 ^ (mx - 1))可不可以到右端点,如果到不了,说明就无法覆盖,直接输出-1。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
int st[maxn][20];
int main() 
	int n, m, x, y, mx = 0;
	memset(st, -1, sizeof(st));
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) 
		scanf("%d%d", &x, &y);
		st[x][0] = max(st[x][0], y);
	
	for (int i = 1; i <= 5e5; i++) 
		if(st[i - 1][0] >= i && st[i - 1][0] > st[i][0])
			st[i][0] = st[i - 1][0];
	
	for (mx = 1; (1 << mx) <= 5e5; mx++)
		for (int j = 0; j <= 5e5; j++) 
			if(st[j][mx - 1] == -1) st[j][mx] = -1;
			else st[j][mx] = st[st[j][mx - 1]][mx - 1];
		
	while(m--) 
		scanf("%d%d", &x, &y);
		int ans = 0;
		if(st[x][mx - 1] < y) 
			printf("-1\n");
			continue;
		
		for (int j = mx - 1; j >= 0; j--) 
			if(st[x][j] < y && st[x][j] > x) 
				ans |= (1 << j);
				x = st[x][j];
			
		
		printf("%d\n", ans + 1);
	
 

  

以上是关于Codeforces 1175E 倍增的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 827D Best Edge Weight 倍增 + 并查集 || 倍增 + 压倍增标记 (看题解)

CF1175E Minimal Segment Cover

LCA(ST)详解 Codeforces932D-倍增+二分搜索

Codeforces 1140G Double Tree 倍增 + dp

区间倍增dpD. Cut——Codeforces Round #717 (Div. 2)

Codeforces 786E. ALT 最小割+倍增