bzoj3745 [Coci2015]Norma
Posted wfj_2048
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3745 [Coci2015]Norma相关的知识,希望对你有一定的参考价值。
Description
Input
第1行,一个整数N;
第2~n+1行,每行一个整数表示序列a。
Output
输出答案对10^9取模后的结果。
Sample Input
4
2
4
1
4
2
4
1
4
Sample Output
109
【数据范围】
N <= 500000
1 <= a_i <= 10^8
【数据范围】
N <= 500000
1 <= a_i <= 10^8
正解:分治。
考虑用分治来处理这个问题。我们在分治时,可以把横跨$mid$的区间计算出来,然后再递归算左右子区间。
我们可以固定左端点,然后统一计算右端点取不同位置的贡献。
可以发现,有$3$种情况:最小值和最大值都在左侧,最小值或最大值有一个在右侧,最小值和最大值都在右侧。
在左端点往左移动的时候,上面$3$中情况形成的区间是依次连续且单调的,只会慢慢往右移。
于是我们可以维护两个单调指针,记录$3$个区间的中间两个端点。
然后统计答案也不难,我们直接把式子拆开,发现只要维护几个前缀和就行了。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define rhl (1000000000) 6 #define N (500010) 7 8 using namespace std; 9 10 int a[N],Min[N],Max[N],smin[N],smax[N],spmin[N],spmax[N],minmax[N],sminmax[N],n,ans; 11 12 il int gi(){ 13 RG int x=0,q=1; RG char ch=getchar(); 14 while ((ch<‘0‘ || ch>‘9‘) && ch!=‘-‘) ch=getchar(); 15 if (ch==‘-‘) q=-1,ch=getchar(); 16 while (ch>=‘0‘ && ch<=‘9‘) x=x*10+ch-48,ch=getchar(); 17 return q*x; 18 } 19 20 il int calc(RG int n){ return (1LL*n*(n+1)>>1)%rhl; } 21 22 il void solve(RG int l,RG int r){ 23 if (l==r){ ans=(ans+1LL*a[l]*a[r])%rhl; return; } RG int mid=(l+r)>>1; 24 Min[mid]=Max[mid]=a[mid],Min[mid+1]=Max[mid+1]=a[mid+1]; 25 for (RG int i=mid-1;i>=l;--i) Min[i]=min(Min[i+1],a[i]),Max[i]=max(Max[i+1],a[i]); 26 for (RG int i=mid+2;i<=r;++i) Min[i]=min(Min[i-1],a[i]),Max[i]=max(Max[i-1],a[i]); 27 smin[mid]=smax[mid]=spmin[mid]=spmax[mid]=minmax[mid]=sminmax[mid]=0; 28 for (RG int i=mid+1;i<=r;++i){ 29 smin[i]=smin[i-1]+Min[i]; if (smin[i]>=rhl) smin[i]-=rhl; 30 smax[i]=smax[i-1]+Max[i]; if (smax[i]>=rhl) smax[i]-=rhl; 31 spmin[i]=(spmin[i-1]+1LL*(i+1)*Min[i])%rhl; 32 spmax[i]=(spmax[i-1]+1LL*(i+1)*Max[i])%rhl; 33 minmax[i]=(minmax[i-1]+1LL*Min[i]*Max[i])%rhl; 34 sminmax[i]=(sminmax[i-1]+1LL*Min[i]*Max[i]%rhl*(i+1))%rhl; 35 } 36 for (RG int i=mid,j=mid+1,k=mid+1;i>=l;--i){ 37 while (j<=r && Min[i]<=Min[j] && Max[i]>=Max[j]) ++j; 38 while (k<=r && (Min[i]<=Min[k] || Max[i]>=Max[k])) ++k; 39 ans=(ans+1LL*Min[i]*Max[i]%rhl*(calc(j-i)-calc(mid-i+1)+rhl))%rhl; if (j>r) continue; 40 if (Min[i]<=Min[j] && Max[i]<Max[j]) 41 ans=(ans+1LL*Min[i]*(spmax[k-1]-spmax[j-1])-1LL*i*Min[i]%rhl*(smax[k-1]-smax[j-1]))%rhl; 42 if (Min[i]>Min[j] && Max[i]>=Max[j]) 43 ans=(ans+1LL*Max[i]*(spmin[k-1]-spmin[j-1])-1LL*i*Max[i]%rhl*(smin[k-1]-smin[j-1]))%rhl; 44 if (k>r) continue; ans=(ans+sminmax[r]-sminmax[k-1]-1LL*i*(minmax[r]-minmax[k-1]))%rhl; 45 } 46 solve(l,mid),solve(mid+1,r); return; 47 } 48 49 int main(){ 50 #ifndef ONLINE_JUDGE 51 freopen("norma.in","r",stdin); 52 freopen("norma.out","w",stdout); 53 #endif 54 n=gi(); for (RG int i=1;i<=n;++i) a[i]=gi(); 55 solve(1,n),cout<<(ans%rhl+rhl)%rhl; return 0; 56 }
以上是关于bzoj3745 [Coci2015]Norma的主要内容,如果未能解决你的问题,请参考以下文章