zoukankan      html  css  js  c++  java
  • 刷题总结——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;
    }
  • 相关阅读:
    现实世界的Windows Azure:采访圣地亚哥公共安全小组的技术经理Adrian Gonzalez
    Casablanca发布:一个用C++访问云的本地类库
    现实世界的Windows Azure:采访IDV解决方案的副总经理Scott Caulk
    Rock Paper Azure Challenge春季比赛来了!
    上海职场六大关键词完全搜集之:才市
    理解 Delphi 的类(十一) 深入类中的方法[8] 抽象方法与抽象类
    理解 Delphi 的类(十一) 深入类中的方法[10] 构造方法与析构方法
    TScreen 类 获取字体列表
    理解 Delphi 的类(十一) 深入类中的方法[9] 不能被覆盖的方法与不能被继承的类
    理解 Delphi 的类(十一) 深入类中的方法[13] 方法的调用约定
  • 原文地址:https://www.cnblogs.com/AseanA/p/7768243.html
Copyright © 2011-2022 走看看