BZOJ3745: [Coci2015]Norma

首先分治。

那么对于区间$[l,r]$中的答案。

我们只考虑经过$mid$和$mid+1$的答案。

然后枚举左端点$L$,计算右端点的所有答案。

设$mn=min[l,mid]$,$mx=max[l,mid]$

令a为最大的位置使得$[mid+1,a]$的所有元素都大于$mn$

 b为最大的位置使得$[mid+1,a]$的所有元素都小于$mx$

那么右端点被$a$,$b$两个位置分成三段,分类讨论。

假设$a<b$,($a>b$的情况同理)。

若$j\leq a$,对答案有$mx*mn*\sum_{j=mid+1}^a (j-i+1)$的贡献。

若$a<j\leq b$,对答案有$mx*(\sum_{a+1}^b min[mid+1,j]*j - \sum_{j=mid+1}^b min[mid+1,j]*(i-1))$

若$b<j\leq r$,对答案有$\sum_{j=b+1}^r min[mid+1,j]*max[mid+1,j]*j - \sum_{j=b+1}^r min[mid+1,r]*max[mid+1,r]*(i-1)$

不难发现,上面的式子都是可以预处理的。

$T(n)=2*T(n/2)+O(n)$,这东西是$O(nlogn)$的。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define M 500010
 4 #define MOD 1000000000
 5 #define inf 2147483647
 6 int a[M];
 7 int Ans;
 8 int mn[M], mx[M], mnj[M], mxj[M], mnmx[M], mnmxj[M];
 9 inline void Do(int l, int r) {
10     if(l == r) {
11         Ans += 1ll * a[l] * a[l] % MOD;
12         if(Ans >= MOD) Ans -= MOD;
13         return;
14     }
15     int mid = (l + r) / 2;
16     Do(l, mid); Do(mid + 1, r);
17     mn[mid] = mx[mid] = mnj[mid] = mxj[mid] = 0;
18     mnmx[mid] = mnmxj[mid] = 0;
19     int Max = 0, Min = inf;
20     for(int i = mid + 1; i <= r; ++ i) {
21         Max = max(Max, a[i]);
22         Min = min(Min, a[i]);
23         mn[i] = mn[i - 1] + Min;
24         if(mn[i] >= MOD) mn[i] -= MOD;
25         mx[i] = mx[i - 1] + Max;
26         if(mx[i] >= MOD) mx[i] -= MOD;
27         mnj[i] = mnj[i - 1] + 1ll * Min * i % MOD;
28         if(mnj[i] >= MOD) mnj[i] -= MOD;
29         mxj[i] = mxj[i - 1] + 1ll * Max * i % MOD;
30         if(mxj[i] >= MOD) mxj[i] -= MOD;
31         mnmx[i] = mnmx[i - 1] + 1ll * Max * Min % MOD;
32         if(mnmx[i] >= MOD) mnmx[i] -= MOD;
33         mnmxj[i] = mnmxj[i - 1] + 1ll * Max * Min % MOD * i % MOD;
34         if(mnmxj[i] >= MOD) mnmxj[i] -= MOD;
35     }
36     Max = 0, Min = inf;
37     int A = mid, B = mid;
38     for(int i = mid; i >= l; -- i) {
39         Max = max(Max, a[i]);
40         Min = min(Min, a[i]);
41         while(a[A + 1] >= Min && A < r) ++ A;
42         while(a[B + 1] <= Max && B < r) ++ B;
43         int aa = min(A, B), bb = max(A, B);
44         Ans += 1ll * Min * Max % MOD * ((1ll * (mid + aa - i - i + 3) * (aa - mid) / 2ll) % MOD) % MOD;
45         if(Ans >= MOD) Ans -= MOD;
46         if(A < B) {
47             Ans += 1ll * Max * ((mnj[bb] - mnj[aa] - 1ll * (i - 1) * (mn[bb] - mn[aa]) % MOD) % MOD + MOD) % MOD;
48             if(Ans >= MOD) Ans -= MOD;
49         }
50         else {
51             Ans += 1ll * Min * ((mxj[bb] - mxj[aa] - 1ll * (i - 1) * (mx[bb] - mx[aa]) % MOD) % MOD + MOD) % MOD;
52             if(Ans >= MOD) Ans -= MOD;
53         }
54         Ans += (mnmxj[r] - mnmxj[bb]);
55         if(Ans >= MOD) Ans -= MOD;
56         if(Ans < 0) Ans += MOD;
57         Ans += (MOD - (1ll * (i - 1) * (mnmx[r] - mnmx[bb] + MOD) % MOD));
58         if(Ans >= MOD) Ans -= MOD;
59     }
60 }
61 int main() {
62     int n;
63     scanf("%d", &n);
64     for(int i = 1; i <= n; ++ i) {
65         scanf("%d", &a[i]);
66     }
67     Do(1, n);
68     printf("%d\n", Ans);
69 }

 

posted @ 2018-08-09 22:48  iamunstoppable  阅读(147)  评论(0编辑  收藏  举报