zoukankan      html  css  js  c++  java
  • 【HDU 4343】Interval query(倍增)

    BUPT2017 wintertraining(15) #8D

    题意

    给你x轴上的N个线段,M次查询,每次问你[l,r]区间里最多有多少个不相交的线段。(0<N, M<=100000)
    限时15000 MS

    题解

    如果不看限时,当作是1000MS的话= =,那么可以用倍增来做。
    先按右端点排序。
    可以去掉一下包含了其它区间的区间,可以优化一点点。
    用 f[i][j] 表示 i 节点下 (2^n) 个不相交的线段下标。
    预处理出 f 数组。
    查询的时候,左端点用二分,然后右端点用倍增来找。
    实际上不用倍增,也可以卡时间过。

    代码

    780ms

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define N 100005
    using namespace std;
    struct Seg{
        int s,e;
        bool operator < (const Seg &b) const{
        	return e<b.e||e==b.e&&s>b.s;
        }
    }seg[N];
    int n,m;
    int f[N][32];
    int main(){
    	while(~scanf("%d %d", &n, &m)){
    		for(int i=0;i<n;++i)
    			scanf("%d %d", &seg[i].s, &seg[i].e);
    		memset(f,-1,sizeof f);
    		sort(seg,seg+n);
    		int nn=0;
    		for(int i=1;i<n;++i)
    			if(seg[nn].s<seg[i].s)
    				seg[++nn]=seg[i];
    		++nn;
    		for(int i=0;i<nn;++i){
    			f[i][0]=i+1;
    			while(f[i][0]<nn&&seg[f[i][0]].s<seg[i].e)++f[i][0];
    			if(f[i][0]==nn)f[i][0]=-1;
    		}
    		for(int j=0;j<30;++j)
    		for(int i=0;i<nn;++i)
    			if(f[i][j]!=-1)
    				f[i][j+1]=f[f[i][j]][j];
    		for(int i=1,s,e;i<=m;++i){
    			scanf("%d %d", &s, &e);
    			int l=0, r=nn-1;
    			while(l<r){
    				int m=l+r>>1;
    				if(seg[m].s<s)
    					l=m+1;
    				else
    					r=m;
    			}
    			if(seg[l].e>e||seg[l].s<s)puts("0");
    			else{
    				int ans=1;
    				for(int j=29;j>=0;--j){
    					if(f[r][j]!=-1&&seg[f[r][j]].e<=e){
    						r=f[r][j];
    						ans+=(1<<j);
    					}
    				}
    				printf("%d
    ", ans);
    			}
    		}
    	}
    	return 0;
    }
    

    1045ms

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define N 100005
    using namespace std;
    struct Seg {
        int s, e;
        bool operator < (const Seg &b) const {
            return e < b.e || e == b.e && s > b.s;
        }
    } seg[N];
    int n, m;
    int main() {
        while(~scanf("%d %d", &n, &m)) {
            for(int i = 0; i < n; ++i)
                scanf("%d %d", &seg[i].s, &seg[i].e);
            sort(seg, seg + n);
            int nn = 0;
            for(int i = 1; i < n; ++i)
                if(seg[nn].s < seg[i].s)
                    seg[++nn] = seg[i];
            ++nn;
            for(int i = 1, s, e; i <= m; ++i) {
                scanf("%d %d", &s, &e);
                int l = 0, r = nn - 1;
                while(l < r) {
                    int m = l + r >> 1;
                    if(seg[m].s < s)
                        l = m + 1;
                    else
                        r = m;
                }
                if(seg[l].e > e || seg[l].s < s)puts("0");
                else {
                    int ans = 1;
                    for(int i = l, j = l + 1; j < nn && seg[j].e <= e; ++j) {
                        if(seg[i].e <= seg[j].s) {
                            i = j;
                            ++ans;
                        }
                    }
                    printf("%d
    ", ans);
                }
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Treap 树堆 容易实现的平衡树
    (转)Maven实战(二)构建简单Maven项目
    (转)Maven实战(一)安装与配置
    根据请求头跳转判断Android&iOS
    (转)苹果消息推送服务器 php 证书生成
    (转)How to renew your Apple Push Notification Push SSL Certificate
    (转)How to build an Apple Push Notification provider server (tutorial)
    (转)pem, cer, p12 and the pains of iOS Push Notifications encryption
    (转)Apple Push Notification Services in iOS 6 Tutorial: Part 2/2
    (转)Apple Push Notification Services in iOS 6 Tutorial: Part 1/2
  • 原文地址:https://www.cnblogs.com/flipped/p/HDU4343.html
Copyright © 2011-2022 走看看