zoukankan      html  css  js  c++  java
  • bzoj 3745 [Coci2015]Norma——序列分治

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3745

    如果分治,就能在本层仅算过 mid 的区间了。

    可以从中间到左边地遍历左边,给右边两个指针,表示第一个更新左边造成的最小值/最大值的位置。

    两个位置共同的左边可以公式算长度,用左边的最值算;两个位置共同的右边可以预处理,处理出 算上长度(相对mid的)的最值乘积求和 与 不算长度的最值乘积求和(都是前缀),把前者加到答案里,后者乘上左边到mid的长度加到答案里即可;两个位置夹着的位置判断一下可以用左边的最大值还是最小值,所以要预处理右边最大值/最小值的算长度/不算长度前缀和,然后和公共右边一样的处理方法即可。

    取模的地方要注意!可能加了一个东西,就不能再+mod、upd( ),而要直接upd( )。

    注意把 l-1 位置的各种值赋成0。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=5e5+5,mod=1e9;
    int n,a[N],ans,s0[N],s1[N],s2[N];//s:可加入ans,相对长度
    int ml0[N],ml1[N],ml2[N];//ml:单纯乘积相加
    int rdn()
    {
        int ret=0;bool fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return fx?ret:-ret;
    }
    void upd(int &x){x-=(x>=mod?mod:0);}
    ll calc(int a){return (ll)a*(a+1)>>1ll;}
    int dis(int x,int y){return y-x+1;}
    void solve(int l,int r)
    {
        if(l==r)
        {
            s2[l]=ml2[l]=(ll)a[l]*a[l]%mod;
            s1[l]=ml1[l]=s0[l]=ml0[l]=a[l];
            s2[l-1]=s1[l-1]=s0[l-1]=ml2[l-1]=ml1[l-1]=ml0[l-1]=0;//
            ans+=s2[l]; upd(ans);
            return;
        }
        int mid=l+r>>1;
        solve(l,mid); solve(mid+1,r);
    
        int lo=a[mid],hi=a[mid],p0=mid+1,p1=mid+1;
        for(int i=mid,cd=1;i>=l;i--,cd++)
        {
            hi=max(hi,a[i]); lo=min(lo,a[i]);
            while(a[p0]<=hi&&p0<=r) p0++;
            while(a[p1]>=lo&&p1<=r) p1++;
            int tl=min(p0,p1)-1,tr=max(p0,p1);
    //        printf("l=%d r=%d hi=%d lo=%d p0=%d p1=%d
    ",l,r,hi,lo,p0,p1);
            
            int d=dis(mid+1,tl);
            ans=(ans+( (ll)cd*d+calc(d) )%mod*lo%mod*hi)%mod;
    //        printf("ans=%d ",ans);
    
            ans=(ans+s2[r]-s2[tr-1])%mod+mod; upd(ans);
            ans=ans+(ll)(ml2[r]-ml2[tr-1])*cd%mod;//cd not dis(i,tr-1)
            if(ans<0) ans+=mod; else upd(ans);//if
    //        printf("ans=%d ",ans);
    
            if(p1<p0)//最小值已更新
            {
                ans=ans+(ll)hi*(s1[tr-1]-s1[tl])%mod;
                if(ans<0)ans+=mod; else upd(ans);
                ans=(ans+(ll)(ml1[tr-1]-ml1[tl])*cd%mod*hi%mod);//cd
                if(ans<0) ans+=mod; else upd(ans);//if
            }
            if(p0<p1)//最大值已更新
            {
    //            printf("tl=%d tr=%d dis(i,tl)=%d s0[%d]-s0[%d]=%d lo=%d mml=%d
    ",
    //            tl,tr,dis(i,tl),tr-1,tl,s0[tr-1]-s0[tl],lo,ml0[tr-1]-ml0[tl]);
                ans=ans+(ll)lo*(s0[tr-1]-s0[tl])%mod;
                if(ans<0)ans+=mod; else upd(ans);
                ans=(ans+(ll)(ml0[tr-1]-ml0[tl])*cd%mod*lo%mod);
                if(ans<0) ans+=mod; else upd(ans);//if
            }
        }
    
        hi=lo=a[l];
        s2[l]=ml2[l]=(ll)hi*lo%mod;  s1[l]=ml1[l]=lo; s0[l]=ml0[l]=hi;
        for(int i=l+1,d=2;i<=r;i++,d++)
        {
            hi=max(hi,a[i]); lo=min(lo,a[i]);
            s2[i]=s2[i-1]+(ll)d*hi%mod*lo%mod; upd(s2[i]);
            s1[i]=s1[i-1]+(ll)d*lo%mod; upd(s1[i]);
            s0[i]=s0[i-1]+(ll)d*hi%mod; upd(s0[i]);
    
            ml2[i]=ml2[i-1]+(ll)hi*lo%mod; upd(ml2[i]);
            ml1[i]=ml1[i-1]+lo; upd(ml1[i]);
            ml0[i]=ml0[i-1]+hi; upd(ml0[i]);
        }
        s2[l-1]=s1[l-1]=s0[l-1]=ml2[l-1]=ml1[l-1]=ml0[l-1]=0;//
    }
    int main()
    {
        n=rdn();
        for(int i=1;i<=n;i++)a[i]=rdn();
        solve(1,n);
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    Codeforces 992C(数学)
    Codeforces 990C (思维)
    Codeforces 989C (构造)
    POJ 1511 Invitation Cards(链式前向星,dij,反向建边)
    Codeforces 1335E2 Three Blocks Palindrome (hard version)(暴力)
    POJ 3273 Monthly Expense(二分)
    POJ 2566 Bound Found(尺取前缀和)
    POJ 1321 棋盘问题(dfs)
    HDU 1506 Largest Rectangle in a Histogram(单调栈)
    POJ 2823 Sliding Window(单调队列)
  • 原文地址:https://www.cnblogs.com/Narh/p/9716621.html
Copyright © 2011-2022 走看看