HDU 4343 Interval query(贪心 + 倍增)
题目链接 2012多校5 Problem D
题意 给定$n$个区间,数字范围在$[0, 10^{9}]$之间,保证左端点严格大于右端点。
然后有$m$个询问,每个询问也为一个区间,数字范围在$[0, 10^{9}]$之间,保证左端点严格大于右端点。
每个询问求的是在当前区间内能得到不相交的给定的区间的数目的最大值。
为了方便我先把给定区间的左端点全部$+1$,询问的区间的左端点也通通$+1$。
然后全部扔到数组里面去离散化一遍,再取出来。
这个时候问题就比较直观了。
其实这个题和 Codeforces 597B 十分类似,只不过现在我们这个题给出了很多区间的询问。
那题我也写了题解,这题之前的预处理和那题基本都一样。
但是那道题只有一个询问,而且是整个区间,这题有很多询问,而且是多个区间。
我们可以考虑倍增。
设$f[i][j]$为从$j$开始考虑取$2^{i}$个区间,跳到的终点的最小值。
若无法取$2^{i}$个区间,那么$f[i][j] = -1$。
于是我们可以根据$f[i][j]$能在$O(logn)$内回答一个询问。
时间复杂度$O(nlogn)$
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) typedef long long LL; const int N = 100010; const int inf = 1e9 + 10; int n, m; int cnt; struct node{ int x, y, s, t; friend bool operator < (const node &a, const node &b){ return a.x == b.x ? a.y < b.y : a.x < b.x; } } a[N], c[N], q[N]; int b[N << 2]; int f[21][N << 2]; int lg[N << 2]; int mx; int tot, itot; bool cmp(const node &a, const node &b){ return a.s == b.s ? a.t > b.t : a.s < b.s; } int main(){ lg[1] = 0; rep(i, 2, 4e5) lg[i] = lg[i >> 1] + 1; while (~scanf("%d%d", &n, &m)){ memset(f, -1, sizeof f); rep(i, 1, n){ scanf("%d%d", &a[i].x, &a[i].y); ++a[i].x; a[i].s = a[i].y; a[i].t = a[i].x + inf; } sort(a + 1, a + n + 1, cmp); cnt = 0; for (int i = 1, j; i <= n;){ j = i + 1; while (j <= n && a[j].t <= a[i].t) ++j; c[++cnt] = a[i]; i = j; } rep(i, 1, m){ scanf("%d%d", &q[i].x, &q[i].y); ++q[i].x; } tot = 0; rep(i, 1, cnt) b[++tot] = c[i].x, b[++tot] = c[i].y; rep(i, 1, m) b[++tot] = q[i].x, b[++tot] = q[i].y; sort(b + 1, b + tot + 1); itot = unique(b + 1, b + tot + 1) - b - 1; rep(i, 1, cnt){ c[i].x = lower_bound(b + 1, b + itot + 1, c[i].x) - b; c[i].y = lower_bound(b + 1, b + itot + 1, c[i].y) - b; } rep(i, 1, m){ q[i].x = lower_bound(b + 1, b + itot + 1, q[i].x) - b; q[i].y = lower_bound(b + 1, b + itot + 1, q[i].y) - b; } mx = max(c[cnt].y, q[m].y); rep(i, 1, mx){ if (i > c[cnt].x) continue; int l = 1, r = cnt; while (l + 1 < r){ int mid = (l + r) >> 1; if (c[mid].x >= i) r = mid; else l = mid + 1; } int t = c[l].x >= i ? l : r; f[0][i] = c[t].y; } rep(i, 1, 19) rep(j, 1, mx) f[i][j] = f[i - 1][f[i - 1][j] + 1]; rep(op, 1, m){ int x = q[op].x, y = q[op].y; int ans = 0; dec(i, 19, 0) if ((~f[i][x]) && (f[i][x] <= y)){ ans += 1 << i; x = f[i][x] + 1; } printf("%d\n", ans); } } return 0; }