zoukankan      html  css  js  c++  java
  • [HNOI2016]序列(莫队,RMQ)

    [HNOI2016]序列(莫队,RMQ)

    洛谷  bzoj

    一眼看不出来怎么用数据结构维护

    然后还没修改

    所以考虑莫队

    以$(l,r-1) -> (l,r)$为例

    对答案的贡献是$Sigma_{i=l}^{r}minval(a[i:r])$

    考虑维护前缀和

    先用单调栈扫出$w[i]$作为最小值的左边界右边界$l_i,r_i$

    然后回到上面的例子贡献就是$frontsum_{r}-frontsum_{rmqmin(l,r)}+w[rmqmin(l,r)]*(rmqmin(l,r)-l+1)$

    完结...等等我好像忘了点啥

    $frontsum_{i}$指的是从i向前拓展的i个包含i的子区间的区间最小值的和,也是可以用单调栈求出来的

    时间复杂度略

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using std::sort;
    typedef long long lint;
    const int N=100011;
    template<typename tp>void read(tp &kk){
        #define ak *
        tp phy=0,ioi=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')ioi=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){phy=phy*10+ch-'0';ch=getchar();}
        kk=phy ak ioi;
    }
    int n,m,bl[N];
    lint w[N];
    int bsize;
    
    int lg[N];
    int lgl[N][17];
    void is()
    {
        for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
        for(int i=1;i<=n;i++) lgl[i][0]=i;
        for(int k=1;k<=lg[n];k++)
        {
            for(int i=1;i-1+(1<<k)<=n;i++)
            {
                lgl[i][k]=w[lgl[i][k-1]]<w[lgl[i+(1<<(k-1))][k-1]]?lgl[i][k-1]:lgl[i+(1<<(k-1))][k-1];
            }
        }
    }
    int rmq(int l,int r){
        return w[lgl[l][lg[r-l+1]]]<
        w[lgl[r-(1<<lg[r-l+1])+1][lg[r-l+1]]]?
        lgl[l][lg[r-l+1]]:
        lgl[r-(1<<lg[r-l+1])+1][lg[r-l+1]];
    }
    
    int li[N],ri[N];
    int st[N],hop;
    void rkk()
    {
        for(int i=1;i<=n;i++)
        {
            while(hop&&w[st[hop]]>w[i])
                ri[st[hop]]=i-1,hop--;
            st[++hop]=i;
            if(i==n)
                while(hop) ri[st[hop]]=i,hop--;
        }
        for(int i=n;i;i--)
        {
            while(hop&&w[st[hop]]>w[i])
                li[st[hop]]=i+1,hop--;
            st[++hop]=i;
            if(i==1)
                while(hop) li[st[hop]]=i,hop--;
        }
    }
    lint fsum[N],bsum[N];
    void baka()
    {
        for(int i=1;i<=n;i++)
            fsum[i]=fsum[li[i]-1]+w[i]*(i-li[i]+1);
        for(int i=n;i;i--)
            bsum[i]=bsum[ri[i]+1]+w[i]*(ri[i]-i+1);
    }
    
    struct ques
    {
        int l,r,id;
        bool friend operator < (ques a,ques b)
        {
            if(bl[a.l]!=bl[b.l]) return bl[a.l]<bl[b.l];
            return bl[a.r]<bl[b.r];
        }
    }q[N];
    
    lint prt[N],tmp;
    
    int main()
    {
        read(n),read(m),bsize=ceil(sqrt(n));
        for(int i=1;i<=n;i++) read(w[i]),bl[i]=(i-1)/bsize+1;
        rkk();
        is();
        baka();
        for(int i=1;i<=m;i++) read(q[i].l),read(q[i].r),q[i].id=i;
        sort(q+1,q+1+m);
        int l=1,r=1;tmp=w[1];
        for(int i=1;i<=m;i++)
        {
            while(r<q[i].r){r++;tmp+=fsum[r]-fsum[rmq(l,r)]+((rmq(l,r)-l+1)*w[rmq(l,r)]);}
            while(l>q[i].l){l--;tmp+=bsum[l]-bsum[rmq(l,r)]+((r-rmq(l,r)+1)*w[rmq(l,r)]);}
            while(r>q[i].r){tmp-=fsum[r]-fsum[rmq(l,r)]+((rmq(l,r)-l+1)*w[rmq(l,r)]);r--;}
            while(l<q[i].l){tmp-=bsum[l]-bsum[rmq(l,r)]+((r-rmq(l,r)+1)*w[rmq(l,r)]);l++;}
            prt[q[i].id]=tmp;
        }
        for(int i=1;i<=m;i++) printf("%lld
    ",prt[i]);
        return 0;
    }
  • 相关阅读:
    pycharm 代码块缩进、左移
    os.popen(cmd) .read() 获取执行后的结果且带有换行符
    数据分析基础路线了解
    Jupyter中python3之numpy练习
    Mysql数据库操作命令行小结
    Mysql配置主从同步的基本步骤
    百度翻译爬虫-Web版(自动生成sign)
    windows中的常用Dos命令
    Cookie安全隐患DOM演示
    bash漏洞技术层面分析(cgi-bin)
  • 原文地址:https://www.cnblogs.com/rikurika/p/11228522.html
Copyright © 2011-2022 走看看