[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
4

Sample Output

109

【数据范围】
N <= 500000
1 <= a_i <= 10^8

HINT

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 }

 

posted @ 2018-04-25 19:14  HocRiser  阅读(252)  评论(0编辑  收藏  举报