zoukankan      html  css  js  c++  java
  • bzoj4130: [PA2011]Kangaroos

    Description

    定义两个区间互相匹配表示这两个区间有交集。

    给出长度为N的区间序列A,M次询问,每次询问序列A中最长的连续子序列,使得子序列中的每个区间都与[L,R]互相匹配
    N<=50000,M<=200000
    把区间看作平面上的点(l,r)(以下均称为点以便区分)
    能匹配A[a..b]的询问点在一个四分之一平面l<=min(A[a..b].r),r>=max(A[a..b].l) 上,于是可以枚举所有长度不超过sqrt(n)的子串,对每种长度的子串可以排序后和询问一起统一处理
    对于更大的区间不能这样暴力处理,那么从[1,n]开始向下分治到区间[l,r],大于sqrt(n)的答案可能跨过区间中点m或在m某侧,而跨过m的可以拆成[a..m][m+1..b]两段,枚举a,b的取值,可以发现每个a或b的取值恰好使一个四分之一平面内的询问点的答案+1,排序后用树状数组处理(类似扫描线),但不同的分治区间之间答案互不影响,所以对每个分治区间要分别开一个树状数组处理。
    总时间复杂度O(nsqrt(n)logn)
    upd:类似http://www.cnblogs.com/ccz181078/p/6607323.html的莫队做法可以去掉一个log,实际运行效果也更好
    #include<bits/stdc++.h>
    const int inf=0x7fffffff;
    int _(){
        int x=0,c=getchar();
        while(c<48)c=getchar();
        while(c>47)x=x*10+c-48,c=getchar();
        return x;
    }
    int n,q,B,p2=0;
    int vs[50007][2],xs[50007];
    struct Q{
        int l,r,id;
    }qs[200007],q2[4000007];
    bool operator<(Q a,Q b){
        return a.l>b.l;
    }
    struct Q2{
        int l,r;
    }q3[1000007];
    bool operator<(Q2 a,Q2 b){
        return a.l>b.l;
    }
    int idp=0,bit[133][50007],ans[200007],lr[50007][2];
    void mins(int&a,int b){if(a>b)a=b;}
    void maxs(int&a,int b){if(a<b)a=b;}
    void calc(int l,int r){
        if(r-l+1<=B)return;
        ++idp;
        int m=l+r>>1;
        int lmx=inf,rmn=0;
        for(int i=m+1;i<=r;++i){
            mins(lmx,vs[i][1]);
            maxs(rmn,vs[i][0]);
            q2[p2++]=(Q){lmx,rmn,idp};
        }
        lmx=inf,rmn=0;
        for(int i=m;i;--i){
            mins(lmx,vs[i][1]);
            maxs(rmn,vs[i][0]);
            q2[p2++]=(Q){lmx,rmn,idp};
        }
        calc(l,m);
        calc(m+1,r);
    }
    void inc(int*a,int w,int mx){
        for(;w<=mx;w+=w&-w)++a[w];
    }
    int sum(int*a,int w){
        int s=0;
        for(;w;w-=w&-w)s+=a[w];
        return s;
    }
    int main(){
        n=_();q=_();B=sqrt(n*4);
        for(int i=1;i<=n;++i){
            xs[i]=vs[i][0]=_();
            vs[i][1]=_();
        }
        std::sort(xs+1,xs+n+1);
        for(int i=1;i<=n;++i)vs[i][0]=std::lower_bound(xs+1,xs+n+1,vs[i][0])-xs;
        for(int i=1;i<=q;++i)qs[i].l=_(),qs[i].r=std::upper_bound(xs+1,xs+n+1,_())-xs-1,qs[i].id=i;
        std::sort(qs+1,qs+q+1);
        calc(1,n);
        std::sort(q2,q2+p2);
        for(int i=1,p=0;i<=q;++i){
            for(;p<p2&&q2[p].l>=qs[i].l;++p)inc(bit[q2[p].id],q2[p].r,n+1);
            for(int j=1;j<=idp;++j){
                maxs(ans[qs[i].id],sum(bit[j],qs[i].r));
            }
        }
        for(int i=1;i<=n;++i)lr[i][0]=inf;
        for(int d=1;d<=B;++d){
            p2=0;
            for(int l=1;l<=n;++l){
                int r=l+d-1;
                if(r>n)break;
                mins(lr[l][0],vs[r][1]);
                maxs(lr[l][1],vs[r][0]);
                q3[p2++]=(Q2){lr[l][0],lr[l][1]};
            }
            std::sort(q3,q3+p2);
            int rmn=inf;
            for(int i=1,p=0;i<=q;++i){
                for(;p<p2&&q3[p].l>=qs[i].l;++p)mins(rmn,q3[p].r);
                if(rmn<=qs[i].r)maxs(ans[qs[i].id],d);
            }
        }
        for(int i=1;i<=q;++i)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    select中的简单联动
    php中的魔术方法简介
    Mysql常用知识
    php程序员需要注意的问题
    android webview "Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.", source: (1)
    gallery调用setselection时有动画的两个方法:
    视频格式资料
    判断网络3,4,2,wifi
    重载的view的ontouchevent不响应的解决办法
    SpannableString用法注意
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6214524.html
Copyright © 2011-2022 走看看