bzoj 3745: [Coci2015]Norma

来源:互联网 发布:出知西安之咸宁翻译 编辑:程序博客网 时间:2024/05/18 15:54

考虑分治,对于区间[l,r],计算左端点在[l,mid],右端点在[mid,r]的区间对答案的影响

然后自己推公式。

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define rep(j,k,l) for (LL j=k;j<=l;++j)#define red(j,k,l) for (LL j=k;j>=l;--j)#define max(a,b) (((a)>(b))?(a):(b))#define min(a,b) (((a)<(b))?(a):(b))#define LL long long#define mod 1000000000#define N 500005using namespace std;LL a[N],n,ans,mx[N],mn[N],sx[N],sn[N],p[N];void solve(LL l,LL r){if (l>r) return;if (l==r){ ans=(ans+a[l]*a[r])%mod; return; }LL mid=l+r>>1;solve(l,mid-1);solve(mid+1,r);LL Mx,Mn,nx,nm;mx[mid]=a[mid];rep(i,mid+1,r) mx[i]=max(a[i],mx[i-1]);red(i,mid-1,l) mx[i]=max(a[i],mx[i+1]);mn[mid]=a[mid];rep(i,mid+1,r) mn[i]=min(a[i],mn[i-1]);red(i,mid-1,l) mn[i]=min(a[i],mn[i+1]);sx[mid]=a[mid];rep(i,mid+1,r) sx[i]=(sx[i-1]+mx[i])%mod;red(i,mid-1,l) sx[i]=(sx[i+1]+mx[i])%mod;sn[mid]=a[mid];rep(i,mid+1,r) sn[i]=(sn[i-1]+mn[i])%mod;red(i,mid-1,l) sn[i]=(sn[i+1]+mn[i])%mod;p[mid]=a[mid]*a[mid]%mod;rep(i,mid+1,r) p[i]=(p[i-1]+mx[i]*mn[i])%mod;red(i,mid-1,l) p[i]=(p[i+1]+mx[i]*mn[i])%mod;Mx=mid,Mn=mid,nx=a[mid],nm=a[mid];red(i,mid,l){LL A=0;nx=max(nx,a[i]);nm=min(nm,a[i]);while (Mx<r&&mx[Mx+1]<=nx) Mx++;while (Mn<r&&mn[Mn+1]>=nm) Mn++;if (Mx==Mn) A=(nx*nm%mod*(Mx-mid+1)%mod+p[r]-p[Mx]+mod)%mod;else if (Mx<Mn) A=(nx*nm%mod*(Mx-mid+1)+(sx[Mn]-sx[Mx]+mod)*nm+p[r]-p[Mn]+mod)%mod; else A=(nx*nm%mod*(Mn-mid+1)+(sn[Mx]-sn[Mn]+mod)*nx+p[r]-p[Mx]+mod)%mod;//printf("%lld %lld\n",Mx,Mn);ans=(ans+(1-i)*A%mod+mod)%mod;//printf("-!-%lld\n",ans);//printf("----%lld %lld %lld %lld\n",l,r,ans,A);}Mx=mid,Mn=mid,nx=a[mid],nm=a[mid];rep(i,mid,r){LL A=0;nx=max(nx,a[i]);nm=min(nm,a[i]);while (Mx>l&&mx[Mx-1]<=nx) Mx--;while (Mn>l&&mn[Mn-1]>=nm) Mn--;if (Mx==Mn) A=(nx*nm%mod*(mid-Mx+1)%mod+p[l]-p[Mx]+mod)%mod;else if (Mx>Mn) A=(nx*nm%mod*(mid-Mx+1)+(sx[Mn]-sx[Mx]+mod)*nm+p[l]-p[Mn]+mod)%mod; else A=(nx*nm%mod*(mid-Mn+1)+(sn[Mx]-sn[Mn]+mod)*nx+p[l]-p[Mx]+mod)%mod;ans=(ans+i*A%mod)%mod;//printf("-*-%lld\n",ans);//printf("----%lld %lld %lld %lld\n",l,r,ans,A);}}int main(){//freopen("1.in","r",stdin);//freopen("1.out","w",stdout);scanf("%lld",&n);rep(i,1,n) scanf("%lld",a+i);solve(1,n);printf("%lld\n",ans);system("pause");}

原创粉丝点击