Sunny_r
2020-01-16 22:28:05
今天下午老师找了一道题让做一个半小时,当做小练,好像也许或许大概可能和以前一道题有点像,一眼看上去
题面:
求
考场思路:先把每个点按照权值从小到大排序,保证
正解:分治就好了啦,每次将左端点从
所以我们考虑如何统计贡献呢?这里就要分情况啦,假设
首先设
1.首先对于
2.对于
考虑维护
所以上述贡献即为
3.对于
考虑维护
所以上述贡献即为
讨论到这里就愉快的结束啦
那么对于
再维护一个
#include <iostream>
#include <cstdio>
#define ll long long
#define int long long
using namespace std;
const int N = 5e5 + 5, inf = 0x3f3f3f3f, mod = 1e9;
int n;
ll mn[N], mx[N], ans, a[N], smn[N], smx[N], smni[N], smxi[N], nx[N], nxi[N];
inline int read()
{
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
void solve(int L, int R)
{
if(L == R) return ans = (ans + a[L] * a[L] % mod) % mod, void();//*1而不是*L
int mid = (L + R) >> 1;
solve(L, mid); solve(mid + 1, R);
mn[mid] = mx[mid] = smn[mid] = smx[mid] = nx[mid] = nxi[mid] = smni[mid] = smxi[mid] = 0;//
mn[mid + 1] = mx[mid + 1] = smn[mid + 1] = smx[mid + 1] = a[mid + 1];
smni[mid + 1] = smxi[mid + 1] = a[mid + 1] * (mid + 1) % mod;
nx[mid + 1] = a[mid + 1] * a[mid + 1] % mod;
nxi[mid + 1] = a[mid + 1] * a[mid + 1] % mod * (mid + 1) % mod;
for(int w = mid + 2; w <= R; w ++)
{
mn[w] = min(a[w], mn[w - 1]); mx[w] = max(mx[w - 1], a[w]);
smn[w] = (smn[w - 1] + mn[w]) % mod; smx[w] = (smx[w - 1] + mx[w]) % mod;
smni[w] = (smni[w - 1] + mn[w] * w % mod) % mod; smxi[w] = (smxi[w - 1] + mx[w] * w % mod) % mod;
nx[w] = (nx[w - 1] + mn[w] * mx[w] % mod) % mod; nxi[w] = (nxi[w - 1] + mn[w] * mx[w] % mod * w % mod) % mod;
}
//smx, smn......因为取模了所以要转正
ll Mn = inf, Mx = 0, j = mid + 1, k = mid + 1, res;
for(int l = mid; l >= L; l --)
{
if(j < mid + 1) j = mid + 1;
if(k < mid + 1) k = mid + 1;
Mn = min(Mn, a[l]); Mx = max(Mx, a[l]);
while(j <= R && mn[j] >= Mn) j ++; j --;
while(k <= R && mx[k] <= Mx) k ++; k --;
if(j <= k)
{
res = Mn * Mx % mod * (((mid + 1 + j) * (j - mid) / 2) % mod - (j - mid) * (l - 1) % mod + mod) % mod;
ans = ((ans + res) % mod + mod) % mod;
res = Mx * (((smni[k] - smni[j] + mod) % mod - (smn[k] - smn[j] + mod) % mod * (l - 1) % mod + mod) % mod) % mod;
ans = ((ans + res) % mod + mod) % mod;
res = ((nxi[R] - nxi[k] + mod) % mod - (nx[R] - nx[k] + mod) % mod * (l - 1) % mod + mod) % mod;
ans = ((ans + res) % mod + mod) % mod;
}
else
{
res = Mn * Mx % mod * (((mid + 1 + k) * (k - mid) / 2) % mod - (k - mid) * (l - 1) % mod + mod) % mod;
ans = ((ans + res) % mod + mod) % mod;
res = Mn * (((smxi[j] - smxi[k] + mod) % mod - (smx[j] - smx[k] + mod) % mod * (l - 1) % mod + mod) % mod) % mod;
ans = ((ans + res) % mod + mod) % mod;
res = ((nxi[R] - nxi[j] + mod) % mod - (nx[R] - nx[j] + mod) % mod * (l - 1) % mod + mod) % mod;
ans = ((ans + res) % mod + mod) % mod;
}
}
}
signed main()
{
freopen("C.in", "r", stdin);
freopen("C.out", "w", stdout);
n = read();
for(int i = 1; i <= n; i ++) a[i] = read();
solve(1, n); printf("%lld\n", ans);
fclose(stdin);
fclose(stdout);
return 0;
}
/*
4
2 4 1 4
*/