[ 分治 ] [ COCI2015 ] BZOJ3745

来源:互联网 发布:深圳小拨网络 skype 编辑:程序博客网 时间:2024/05/01 07:03

分治到一个区间时枚举左端点,然后分类讨论一下就好了。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());}const int N=500010;const int M=1000000000;int k,n,m,p;int a[N];int mn[N],mx[N],smn[N],smx[N],imn[N],imx[N],smnmx[N],imnmx[N];int Ans;inline void Add(int& x,int y){    x=(x+y)%M;}inline int Sum(int l,int r){    return 1ll*(r+l)*(r-l+1)/2%M;}void Solve(int l,int r){    if(l==r){        Add(Ans,1ll*a[l]*a[l]%M);//      printf("%d %d %d\n",l,r,a[l]*a[l]);        return;    }    int Mid=l+r>>1;    Solve(l,Mid);Solve(Mid+1,r);    mn[Mid+1]=mx[Mid+1]=smn[Mid+1]=smx[Mid+1]=a[Mid+1];    smnmx[Mid+1]=1ll*mn[Mid+1]*mx[Mid+1]%M;    imnmx[Mid+1]=1ll*smnmx[Mid+1]*(Mid+2)%M;    imn[Mid+1]=imx[Mid+1]=1ll*(Mid+2)*a[Mid+1]%M;    for(int i=Mid+2;i<=r;i++){        mn[i]=min(mn[i-1],a[i]);mx[i]=max(mx[i-1],a[i]);        smn[i]=(smn[i-1]+mn[i])%M;smx[i]=(smx[i-1]+mx[i])%M;        imn[i]=(imn[i-1]+1ll*mn[i]*(i+1))%M;imx[i]=(imx[i-1]+1ll*mx[i]*(i+1))%M;        smnmx[i]=(smnmx[i-1]+1ll*mn[i]*mx[i])%M;        imnmx[i]=(imnmx[i-1]+1ll*mn[i]*mx[i]%M*(i+1))%M;    }    int j=Mid,k=Mid;    int Mn=a[Mid],Mx=a[Mid];    imn[Mid]=smn[Mid]=imx[Mid]=smx[Mid]=0;    imnmx[Mid]=smnmx[Mid]=0;    for(int i=Mid;i>=l;i--){    int Res=Ans;        Mn=min(Mn,a[i]);Mx=max(Mx,a[i]);        while(j<r&&mn[j+1]>=Mn)j++;        while(k<r&&mx[k+1]<=Mx)k++;        Add(Ans,1ll*Mn*Mx%M*Sum(Mid+2-i,min(j,k)-i+1)%M);        if(j<k){            Add(Ans,1ll*Mx*(imn[k]-imn[j])%M);            Add(Ans,-1ll*Mx*i%M*(smn[k]-smn[j])%M);            Add(Ans,(imnmx[r]-imnmx[k])%M);            Add(Ans,-1ll*i*(smnmx[r]-smnmx[k])%M);        }else{            Add(Ans,1ll*Mn*(imx[j]-imx[k])%M);            Add(Ans,-1ll*Mn*i%M*(smx[j]-smx[k])%M);            Add(Ans,(imnmx[r]-imnmx[j])%M);            Add(Ans,-1ll*i*(smnmx[r]-smnmx[j])%M);        }    }}int main(){    Read(n);    for(int i=1;i<=n;i++)Read(a[i]);    Solve(1,n);    cout<<(Ans+M)%M<<endl;    return 0;}