刷题总结——Interval query(hdu4343倍增+贪心)

题目:

Problem Description

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.

Output

For 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

Author

HIT

Source

 

题解:

  首先容易想到那些覆盖了其他较小区间的区间是可以忽略的··因为对于每个询问要尽量多取区间···

  然后考虑对于每个询问···我们肯定会采取贪心策略,从询问范围的左端开始找··如果找到一个区间就取该区间··然后跳到该区间的右端··再继续向右边找下一个区间··这个方法肯定是最优的····

  至于如何寻找,我们考虑倍增(现在发现关于区间的一些查询问题如果用数据结构解决不了的话基本上就是倍增了··),用g[i][j]表示从i点出发··在找到2^j个互不相交的区间后到达的最右端点··首先预处理g[i][0],然后再一次处理g[i][1],g[i][2]....即可

  最后对于每个询问我们像找lca那样跳区间··边跳边更新答案就可以了

代码:

  

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=2e5+5;
inline int R(){
    char c;int f=0;
    for(c=getchar();c<'0'||c>'9';c=getchar());
    for(;c<='9'&&c>='0';c=getchar())    f=(f<<3)+(f<<1)+c-'0';
    return f;
}
struct node{int l,r;}a[N],q[N],c[N];
int b[N*2],cnt,n,m,stack[N],top=0,bel[N*2],g[N*2][25];
inline void lsh(){
    sort(b+1,b+cnt+1);
    cnt=unique(b+1,b+cnt+1)-b-1;
    for(int i=1;i<=n;i++){
        a[i].l=lower_bound(b+1,b+cnt+1,a[i].l)-b;
        a[i].r=lower_bound(b+1,b+cnt+1,a[i].r)-b;
    }
    for(int i=1;i<=m;i++){
        q[i].l=lower_bound(b+1,b+cnt+1,q[i].l)-b;
        q[i].r=lower_bound(b+1,b+cnt+1,q[i].r)-b;
    }
}
inline bool cmp(node a,node b){
    if(a.l==b.l)  return a.r>b.r;
    else  return a.l<b.l;
}
inline void pre(){
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        while(top&&a[i].l>=a[stack[top]].l&&a[i].r<=a[stack[top]].r)  top--;
        stack[++top]=i;
    }
    n=0;
    for(int i=1;i<=top;i++)    c[++n]=a[stack[i]];
    int tail=1;
    for(int i=1;i<=n;i++){
        while(tail<=c[i].l)    g[tail][0]=c[i].r,tail++;
    }
}
inline int query(int l,int r){
    int ans=0,i=l;
    for(int j=20;j>=0;j--)
        if(g[i][j]&&g[i][j]<=r)    i=g[i][j],ans+=(1<<j);
    return ans;
}
int main(){
    //freopen("a.in","r",stdin);
    while(scanf("%d%d",&n,&m)!=EOF){ 
        top=cnt=0;memset(g,0,sizeof(g));
        for(int i=1;i<=n;i++)    a[i].l=R(),a[i].r=R(),b[++cnt]=a[i].l,b[++cnt]=a[i].r;
        for(int i=1;i<=m;i++)    q[i].l=R(),q[i].r=R(),b[++cnt]=q[i].l,b[++cnt]=q[i].r;
        lsh();pre();
        for(int i=1;i<=20;i++)
            for(int j=1;j<=cnt;j++)    g[j][i]=g[g[j][i-1]][i-1];
        for(int i=1;i<=m;i++)    cout<<query(q[i].l,q[i].r)<<endl;
        
    }
    return 0;
}

 

posted @ 2017-11-01 20:16  AseanA  阅读(646)  评论(0编辑  收藏  举报