题解 HDU 4343 Interval query
题面
This is a very simple question. There are N intervals in number axis, and M queries just like “QUERY(a,b)” indicate asking the maximum number of the disjoint intervals between (a,b) .
Input
There are several test cases. For each test case, the first line contains two integers N, M (0<N, M<=100000) as described above. In each following N lines, there are two integers indicate two endpoints of the i-th interval. Then come M lines and each line contains two integers indicating the endpoints of the i-th query.
You can assume the left-endpoint is strictly less than the right-endpoint in each given interval and query and all these endpoints are between 0 and 1,000,000,000.OutputFor each query, you need to output the maximum number of the disjoint intervals in the asked interval in one line.
Sample Input
3 2 1 2 2 3 1 3 1 2 1 3
Sample Output
1 2
题面大意:
给你$n$个区间,再给你$m$个询问,每个询问问你一段区间最多能被多少个没有重叠部分的区间覆盖。
做法:
我们先思考询问区间为$[1,n]$的情况,这道题我们大家肯定都做过,是一道贪心,将区间按最后一个关键字排序就行了。
然后我们再考虑特殊情况:询问一个区间最多能被多少个区间覆盖,而且这些区间无重叠且无间隙(即首尾相连)
这也好做,我们只要利用一个倍增,$f[i][j]$表示i位置往后放j个区间最近能到哪一位,然后用$f[i][j] = f\big[f[i][j-1]\big]\big[j-1\big]$就行了
简单情况分析完了,我们来看本题,因为本题和我们前面说的第二种情况十分相似,所以我们只要加一个缩放的操作就行了,即$f[i][j]$不一定在$i$位置上放有东西。
那么缩放怎么处理?
我们就要用到第一种情况了,贪心处理,我们先将区间按第二关键字排序,然后我们只需记录一下你从第一位处理到哪一位了,然后下一次再从该位改到这个区间的右端点就行了,转移就变成了$f[i][j]=\min(f[i][j],f\big[f[i][j-1]\big]\big[j-1\big])$
另外,本题数据较大,需要离散化,怎么离散化我就不说了
具体看代码
#include<bits/stdc++.h>
using namespace std;
inline int max(int x,int y) {return x>y?x:y;}
inline int min(int x,int y) {return x<y?x:y;}
inline int read()
{
int x=0,f=1;
char c=getchar();
while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0' && c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
const int N=100005;
int f[4*N][22],n,m,num[4*N],len;
struct node
{
int l,r;
}q[N],a[N];
inline bool cmp(node x,node y) {return x.r<y.r;}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(f,0x7f,sizeof(f));
len=0;
int maxr=0;
for(int i=1;i<=n;i++) a[i].l=read(),a[i].r=read(),num[++len]=a[i].l,num[++len]=a[i].r;
for(int i=1;i<=m;i++) q[i].l=read(),q[i].r=read(),num[++len]=q[i].l,num[++len]=q[i].r;
sort(num+1,num+len+1);
len=unique(num+1,num+len+1)-num-1;
maxr=num[len];
for(int i=1;i<=n;i++) a[i].l=lower_bound(num+1,num+len+1,a[i].l)-num;
for(int i=1;i<=n;i++) a[i].r=lower_bound(num+1,num+len+1,a[i].r)-num;
for(int i=1;i<=m;i++) q[i].l=lower_bound(num+1,num+len+1,q[i].l)-num;
for(int i=1;i<=m;i++) q[i].r=lower_bound(num+1,num+len+1,q[i].r)-num;
sort(a+1,a+n+1,cmp);
int posl=0;
for(int i=1;i<=n;i++)
{
for(int j=posl+1;j<=a[i].l;j++) f[j][0]=min(f[j][0],a[i].r);
posl=max(posl,a[i].l);
}
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=maxr;i++)
{
if(f[i][j-1]>maxr) break;
f[i][j]=f[f[i][j-1]][j-1];
}
for(int i=1;i<=m;i++)
{
int pos=q[i].l,ans=0;
for(int j=20;j>=0;j--)
if(f[pos][j]<=q[i].r)
{
pos=f[pos][j];
ans+=(1<<j);
}
printf("%d\n",ans);
}
}
return 0;
}

浙公网安备 33010602011771号