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;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/9635799.html