Interval query
题意:
给出数轴上的N个区间,M个询问"QUERY(a, b)", 意为[a, b]之间不相交的集合的最大数量是多少。
解法:
考虑 $O(n)$ 的贪心做法,预处理出对于每一个位置$i$,满足$i \leq L_j$ 的 $R_j$的最小值
这样暴力向后找即可。
用倍增优化这个过程 $O(nlogn)$
#include <bits/stdc++.h> #define N 100010 using namespace std; struct node { int l,r; }a[N],q[N]; int n,m,tot0; int a0[N<<2]; int minR[N<<2][21]; bool cmp(node a,node b) { return a.l<b.l; } int ask(int l,int r) { int x = l,ans = 0; for(int i=20;~i;i--) if(minR[x][i] <= r) x = minR[x][i], ans += (1<<i); return ans; } int main() { while(~scanf("%d%d",&n,&m)) { a0[0] = 0; for(int i=1;i<=n;i++) { scanf("%d%d",&a[i].l,&a[i].r); a0[++a0[0]] = a[i].l; a0[++a0[0]] = a[i].r; } for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); a0[++a0[0]] = q[i].l; a0[++a0[0]] = q[i].r; } sort(a0+1,a0+a0[0]+1); tot0=1; for(int i=2;i<=a0[0];i++) if(a0[i]!=a0[i-1]) a0[++tot0] = a0[i]; for(int i=1;i<=n;i++) { a[i].l = lower_bound(a0+1,a0+tot0+1,a[i].l) - a0; a[i].r = lower_bound(a0+1,a0+tot0+1,a[i].r) - a0; } sort(a+1,a+n+1,cmp); int j=n,tmpR = tot0+1; for(int i=tot0;i>=1;i--) { while(j>0 && a[j].l >= i) { tmpR = min(tmpR, a[j].r); j--; } minR[i][0] = tmpR; } for(int t=1;t<=20;t++) for(int i=1;i<=tot0;i++) { if(minR[i][t-1]<=tot0) minR[i][t] = minR[minR[i][t-1]][t-1]; else minR[i][t] = tot0+1; } for(int i=1;i<=m;i++) { q[i].l = lower_bound(a0+1,a0+tot0+1,q[i].l) - a0; q[i].r = lower_bound(a0+1,a0+tot0+1,q[i].r) - a0; printf("%d\n",ask(q[i].l,q[i].r)); } } return 0; }