• 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
    ");
    			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
    ", ans + 1);
    	}
    } 
    

      

  • 相关阅读:
    UILabel 设置字体间的距离 和 行与行间的距离
    IB_DESIGNABLE 和 IBInspectable 的使用
    干货博客
    GitHub克隆速度太慢解决方案
    实时(RTC)时钟,系统时钟和CPU时钟
    折腾了好久的vscode配置c/c++语言环境(Windows环境下)
    c语言中的malloc函数
    记录一下关于在工具类中更新UI使用RunOnUiThread犯的极其愚蠢的错误
    记录关于Android多线程的一个坑
    Android中限制输入框最大输入长度
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/10986488.html
Copyright © 2020-2023  润新知