[BZOJ3745][COCI2015]Norma(分治)
3745: [Coci2015]Norma
Time Limit: 20 Sec Memory Limit: 64 MB
Submit: 563 Solved: 249
[Submit][Status][Discuss]Description
Input
第1行,一个整数N;第2~n+1行,每行一个整数表示序列a。Output
输出答案对10^9取模后的结果。Sample Input
4
2
4
1
4Sample Output
109
【数据范围】
N <= 500000
1 <= a_i <= 10^8HINT
Source
[Submit][Status][Discuss]
分治(可以用线段树做,一般分治都是用来代替数据结构的)一般分三种:
1.CDQ分治,在高维偏序中用来处理一维。 (处理在线修改多询问问题)
2.线段树分治,当修改可分裂可撤销时较有效。(处理离线修改全询问问题)
3.二分或三分,处理单调或单峰函数极值问题时有效。(处理在线修改多询问问题)
4.“mid型”,类似树分治,统计跨过mid的区间总数,然后递归道两边继续统计。(处理无修改全询问问题)
具体到这一题,显然是最后一种方法。
https://blog.csdn.net/lych_cys/article/details/51203960
分类讨论一波,处理各种前缀和即可。
不想考虑取模和炸int的问题的话就在确定正确性之前全用long long吧。。
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 4 typedef long long ll; 5 using namespace std; 6 7 const int N=500100,mod=1000000000; 8 int n,ans,a[N],f[N],g[N],Min[N],Max[N],Smn[N],Smx[N],Mmn[N],Mmx[N]; 9 10 int sum(int l,int r){ return (1ll*(l+r)*(r-l+1)>>1)%mod; } 11 12 void solve(int l,int r){ 13 if (l==r) { ans=(ans+1ll*a[l]*a[l])%mod; return; } 14 int mid=(l+r)>>1; int mn=mod,mx=-mod; 15 solve(l,mid); solve(mid+1,r); 16 for (int i=mid; i>=l; i--) Min[i]=mn=min(mn,a[i]),Max[i]=mx=max(mx,a[i]); 17 18 mn=mod,mx=-mod; 19 g[mid]=f[mid]=Smn[mid]=Smx[mid]=Mmn[mid]=Mmx[mid]=0; 20 rep(i,mid+1,r){ 21 Min[i]=mn=min(mn,a[i]); Max[i]=mx=max(mx,a[i]);//min/max 22 Smn[i]=(Smn[i-1]+Min[i])%mod; Smx[i]=(Smx[i-1]+Max[i])%mod;//sufsum of min/max 23 Mmn[i]=(Mmn[i-1]+1ll*Min[i]*i)%mod; Mmx[i]=(Mmx[i-1]+1ll*Max[i]*i)%mod;//sufsum of i*min/max 24 g[i]=(g[i-1]+1ll*mn*mx)%mod; f[i]=(f[i-1]+1ll*i*mn%mod*mx)%mod;//sufsum of min*max && sufsum of i*min*max 25 } 26 27 int j=mid,k=mid; 28 for (int i=mid; i>=l; i--){ 29 while (j<r && Min[i]<a[j+1]) j++; 30 while (k<r && Max[i]>a[k+1]) k++; 31 ans=(ans+1ll*Min[i]*Max[i]%mod*sum(mid-i+2,min(j,k)-i+1))%mod;//[mid+1,min(j,k)] 32 ans=((ans+f[r]-f[max(j,k)]-1ll*(g[r]-g[max(j,k)])*(i-1)%mod)%mod+mod)%mod;//[max(j+k)+1,r] 33 if (j<k) ans=(ans+1ll*Max[i]*(Mmn[k]-Mmn[j]-1ll*(i-1)*(Smn[k]-Smn[j])%mod)%mod+mod)%mod;//[j+1,k] 34 else ans=(ans+1ll*Min[i]*(Mmx[j]-Mmx[k]-1ll*(i-1)*(Smx[j]-Smx[k])%mod)%mod+mod)%mod;//[k+1,j] 35 } 36 } 37 38 int main(){ 39 freopen("bzoj3745.in","r",stdin); 40 freopen("bzoj3745.out","w",stdout); 41 scanf("%d",&n); 42 rep(i,1,n) scanf("%d",&a[i]); 43 solve(1,n); printf("%d\n",ans); 44 return 0; 45 }