ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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\n",ans[i]);
    return 0;
}

 

posted on 2016-12-23 13:49  nul  阅读(413)  评论(0编辑  收藏  举报