zoukankan      html  css  js  c++  java
  • bzoj3745: [Coci2015]Norma

    我要哭了我终于A了,中午没保存然后重推柿子重写然后改一波LL就A了哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈

    这个题我诚实的说%了下题解:就是分治的时候,算左边(l~mid)到右边(mid+1~r)

    枚举右界,仔细想想可以把区间分成3块分情况讨论。接下来就是艰苦卓绝的化柿子了

    我写这种理性的题果然。。。。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9;
    LL getsum(LL st,LL ed){return ((st+ed)*(ed-st+1)/2)%mod;}//等差数列求和
    LL MOD(LL x){return (x%mod+mod)%mod;}
    
    LL a[510000],ans;
    struct Right
    {
        LL st,ed,rmn,rmx;
        Right(){}
        Right(LL ST,LL ED,LL RMN,LL RMX){st=ST,ed=ED,rmn=RMN;rmx=RMX;}
    }R[510000];int Rlen;
    
    LL g[510000],h[510000];
    void cdq(LL l,LL r)
    {
        if(l==r){ans=(ans+a[l]*a[l])%mod;return ;}
        int mid=(l+r)/2;
        
        LL rmn=a[mid+1],rmx=a[mid+1]; Rlen=0;
        R[++Rlen]=Right(mid+1,mid+1,rmn,rmx);
        for(int i=mid+2;i<=r;i++)
        {
            if(rmn>a[i]||rmx<a[i])
            {
                rmn=min(rmn,a[i]);
                rmx=max(rmx,a[i]);
                R[++Rlen]=Right(i,i,rmn,rmx);
            }
            else R[Rlen].ed++;
        }
        
        //--------------------分块---------------------- 
        
        g[Rlen+1]=0;h[Rlen+1]=0;
        for(int i=Rlen;i>=1;i--)
        {
            g[i]= (g[i+1] + (getsum(R[i].st,R[i].ed)*(R[i].rmn*R[i].rmx%mod))%mod )%mod;
            h[i]= (h[i+1] + ((R[i].ed-R[i].st+1)*(R[i].rmn*R[i].rmx%mod))%mod )%mod;
        }
        
        //-----------------------右区间预处理函数g,h------------------------
        
        LL j=0,k=0;    int w=-1;LL Gmn=0,Hmn=0,Gmx=0,Hmx=0;//动态维护中部答案 
        LL lmn=(1LL<<62),lmx=0;
        for(LL i=mid;i>=l;i--)
        {
            lmn=min(lmn,a[i]);
            lmx=max(lmx,a[i]);
            
            while(j<Rlen&&(lmn<=R[j+1].rmn&&lmx>=R[j+1].rmx))
            {
                j++;
                if(j<=k)
                {
                    if(w==0)
                    {
                        Gmx=MOD( Gmx-(getsum(R[j].st,R[j].ed)*R[j].rmx%mod) );
                        Hmx=MOD( Hmx-((R[j].ed-R[j].st+1)*R[j].rmx%mod) );
                    }
                    else
                    {
                        Gmn=MOD( Gmn-(getsum(R[j].st,R[j].ed)*R[j].rmn%mod) );
                        Hmn=MOD( Hmn-((R[j].ed-R[j].st+1)*R[j].rmn%mod) );
                    }
                }
            }
            
            while(k<Rlen&&(lmn<=R[k+1].rmn||lmx>=R[k+1].rmx))
            {
                k++;
                if(lmn<=R[k].rmn&&lmx>=R[k].rmx)
                    Gmn=0, Hmn=0, Gmx=0, Hmx=0;
                else 
                {
                    w=(lmn<=R[k].rmn)?0:1;
                    if(w==0)
                    {
                        Gmx=( Gmx+(getsum(R[k].st,R[k].ed)*R[k].rmx%mod) )%mod;
                        Hmx=( Hmx+((R[k].ed-R[k].st+1)*R[k].rmx%mod) )%mod;
                    }
                    else
                    {
                        Gmn=( Gmn+(getsum(R[k].st,R[k].ed)*R[k].rmn%mod) )%mod;
                        Hmn=( Hmn+((R[k].ed-R[k].st+1)*R[k].rmn%mod) )%mod;
                    }
                }
            }
            
            //-------------------extend&&单调维护中部-------------------------
            
            if(j>0&&j<=r)ans=( ans + ( MOD(getsum(mid+1,R[j].ed)-((R[j].ed-mid)*(i-1)%mod)) * ((lmn*lmx)%mod) %mod ) )%mod;
            //左区间
            
            if(j+1<=k)
            {
                if(w==0)ans=( ans + lmn*MOD(Gmx-((i-1)*Hmx))%mod )%mod;
                else    ans=( ans + lmx*MOD(Gmn-((i-1)*Hmn))%mod )%mod;
            }
            //中部
            
            if(k+1<=r)ans=( ans + MOD( g[k+1]-((i-1)*h[k+1]%mod) ) )%mod;
            //右区间 
        }
        
        cdq(l,mid),cdq(mid+1,r);    
    }
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
        ans=0;cdq(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    [leetcode] 18. 四数之和
    [leetcode] 17. 电话号码的字母组合
    [leetcode] 16. 最接近的三数之和
    [leetcode] 15. 三数之和
    [leetcode] 14. 最长公共前缀
    [leetcode] 13. 罗马数字转整数
    [leetcode] 12. 整数转罗马数字
    [leetcode] 11.盛最多水的容器
    分布式系统中的缓存——笔记整理
    图解HTTP
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9635799.html
Copyright © 2011-2022 走看看