• 【题解】[bzoj 4358] permu【单增莫队】


    题目链接

    题意

    给定排列 (p)(Q) 次询问 (p[l..r]) 的最长值域连续段的长度。

    (1leq n,mleq 5 imes 10^4)

    题解

    记录每个值域连续段的端点往左/右能延伸的最大距离,往 (p[l,r]) 中加入一个数时可以 (O(1)) 维护。于是可以单增莫队。

    (单增莫队做法:(l,r) 在同一块的直接暴力,其他询问按照 (l) 所在块(([L,R]))分组,每一组按 (r) 从小到大排序;处理时从 ([R,r]) 转移到 ([R,r']),再转移到 ([l',r']) 得到答案,最后回滚到 ([R,r'])

    #include<bits/stdc++.h>
    using namespace std;
    int getint(){
        int ans=0;
        char c=getchar();
        while(c<'0'||c>'9')c=getchar();
        while(c>='0'&&c<='9'){
            ans=ans*10+c-'0';
            c=getchar();
        }
        return ans;
    }
    const int N=1e5+10;
    int n,m,blk;
    int p[N];
    struct query{
        int l,r,id;
    };
    bool cmp(const query &a,const query &b){ return a.r<b.r; }
    vector<query>q[N];
    
    int xl[N],xr[N];
    vector<pair<int,int> >lm,rm;
    int ans=0,oldans=0;
    void addl(int x){
        int v=p[x];
        lm.emplace_back(v,xl[v]);
        rm.emplace_back(v,xr[v]);
        xl[v]=xl[v-1]?xl[v-1]:v;
        xr[v]=xr[v+1]?xr[v+1]:v;
        ans=max(ans,xr[v]-xl[v]+1);
        if(xl[v-1]){
            rm.emplace_back(xl[v-1],xr[xl[v-1]]);
            xr[xl[v-1]]=xr[v];
        }
        if(xr[v+1]){
            lm.emplace_back(xr[v+1],xl[xr[v+1]]);
            xl[xr[v+1]]=xl[v];
        }
    }
    void addr(int x){
        int v=p[x];
        xl[v]=xl[v-1]?xl[v-1]:v;
        xr[v]=xr[v+1]?xr[v+1]:v;
        ans=max(ans,xr[v]-xl[v]+1);
        if(xl[v-1])
            xr[xl[v-1]]=xr[v];
        if(xr[v+1])
            xl[xr[v+1]]=xl[v];
    }
    void rollback(){
        ans=oldans;
        for(int i=rm.size()-1;i>=0;--i)xr[rm[i].first]=rm[i].second;
        for(int i=lm.size()-1;i>=0;--i)xl[lm[i].first]=lm[i].second;
        rm.clear();
        lm.clear();
    }
    
    int res[N];
    
    int main(){
        n=getint(),m=getint();
        blk=max(1.0,n/sqrt(m*0.7));
        for(int i=1;i<=n;i++)p[i]=getint();
        for(int i=0;i<m;i++){
            int l=getint(),r=getint();
            if(l/blk==r/blk){
                for(int i=r;i>=l;--i)addl(i);
                res[i]=ans;
                rollback();
                continue;
            }
            query t;t.l=l;t.r=r;t.id=i;
            q[l/blk].push_back(t);
        }
        for(int i=0;i<=n/blk;i++){
            sort(q[i].begin(),q[i].end(),cmp);
            memset(xl,0,sizeof(int)*(n+1));
            memset(xr,0,sizeof(int)*(n+1));
            ans=0;
            int r=(i+1)*blk-1,l=r;
            for(auto q: ::q[i]){
                while(r<q.r)++r,addr(r);
                oldans=ans;
                for(int i=l;i>=q.l;--i)addl(i);
                res[q.id]=ans;
                rollback();
            }
        }
        for(int i=0;i<m;i++)printf("%d
    ",res[i]);
    }
    
    
  • 相关阅读:
    Oracle错误一览表
    CAP原理
    阿里巴巴供应链平台事业部2020届秋招-Java工程师
    IM即时通信软件设计
    邮箱核心业务领域建模
    DDD中的聚合和UML中的聚合以及组合的关系
    对关系建模
    DDD战略设计相关核心概念的理解
    DDD领域建模基本流程
    谈谈Paxos一致性算法和一致性这个名词
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/14251262.html
Copyright © 2020-2023  润新知