• [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;
    }
  • 相关阅读:
    FZU 2112 并查集、欧拉通路
    HDU 5686 斐波那契数列、Java求大数
    Codeforces 675C Money Transfers 思维题
    HDU 5687 字典树插入查找删除
    HDU 1532 最大流模板题
    HDU 5384 字典树、AC自动机
    山科第三届校赛总结
    HDU 2222 AC自动机模板题
    HDU 3911 线段树区间合并、异或取反操作
    CodeForces 615B Longtail Hedgehog
  • 原文地址:https://www.cnblogs.com/rikurika/p/11228522.html
Copyright © 2020-2023  润新知