题意:
给出三个长度为$n$的正整数序列,一个区间$[L,R]$的价值定义为:三个序列中,这个区间的极差(最大值与最小值之差)的乘积。
求所有区间的价值之和。答案对$2^{32}$取模。
思路:
枚举右端点,设三个序列分别是$a,b,c$,线段树维护$a,b,c,ab,ac,bc,abc$的$max-min$的值。线段树每个单位区间$(x,x)$表示序列区间$(x,r)$的$max-min$的值。$a$的$max-min$改变,$ab,ac,abc$都改变。单调栈维护区间的最大最小值。
代码:
1 //#include<bits/stdc++.h> 2 #include <set> 3 #include <map> 4 #include <stack> 5 #include <cmath> 6 #include <queue> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstring> 11 #include <iostream> 12 #include <algorithm> 13 14 #define ll long long 15 #define pll pair<ll,ll> 16 #define pii pair<int,int> 17 #define bug printf("********* ") 18 #define FIN freopen("input.txt","r",stdin); 19 #define FON freopen("output.txt","w+",stdout); 20 #define IO ios::sync_with_stdio(false),cin.tie(0) 21 #define ls root<<1 22 #define rs root<<1|1 23 #define pb push_back 24 #define PI acos(-1.0) 25 26 using namespace std; 27 const int inf = 0x3f3f3f3f; 28 const ll INF = 1e18 + 7; 29 const int maxn = 1e5 + 5; 30 const ll mod = 1ll << 32; 31 const double eps = 1e-6; 32 33 inline ll read() { 34 bool f = 0; 35 ll x = 0; char ch = getchar(); 36 while (ch < '0' || ch>'9') { if (ch == '-')f = 1; ch = getchar(); } 37 while (ch >= '0' && ch <= '9') { x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar(); } 38 return f ? -x : x; 39 } 40 41 ll gcd(ll a, ll b) { 42 return b == 0 ? a : gcd(b, a % b); 43 } 44 45 ll tr[maxn << 2][8]; 46 ll lazy[maxn << 2][4]; 47 48 void push_up(int root) { 49 for (int i = 1; i <= 7; ++i) { 50 tr[root][i] = tr[ls][i] + tr[rs][i]; 51 } 52 } 53 54 void work(int root, ll x, int id, int len) { 55 if (id == 1) { 56 tr[root][1] += x * len; 57 tr[root][4] += tr[root][2] * x; 58 tr[root][5] += tr[root][3] * x; 59 tr[root][7] += tr[root][6] * x; 60 } 61 else if (id == 2) { 62 tr[root][2] += x * len; 63 tr[root][4] += tr[root][1] * x; 64 tr[root][6] += tr[root][3] * x; 65 tr[root][7] += tr[root][5] * x; 66 } 67 else { 68 tr[root][3] += x * len; 69 tr[root][5] += tr[root][1] * x; 70 tr[root][6] += tr[root][2] * x; 71 tr[root][7] += tr[root][4] * x; 72 } 73 lazy[root][id] += x; 74 lazy[root][id] %= mod; 75 for (int i = 1; i <= 7; ++i) { 76 tr[root][i] %= mod; 77 } 78 } 79 80 void push_down(int root, int l, int r) { 81 for (int i = 1; i <= 3; ++i) { 82 if (lazy[root][i]) { 83 int mid = (l + r) >> 1; 84 work(ls, lazy[root][i], i, mid - l + 1); 85 work(rs, lazy[root][i], i, r - mid); 86 lazy[root][i] = 0; 87 } 88 } 89 } 90 91 void update(int root, int l, int r, int ql, int qr, ll x, int id) { 92 if (l >= ql && r <= qr) { 93 work(root, x, id, r - l + 1); 94 return; 95 } 96 push_down(root, l, r); 97 int mid = (l + r) >> 1; 98 if (ql <= mid) update(ls, l, mid, ql, qr, x, id); 99 if (qr > mid) update(rs, mid + 1, r, ql, qr, x, id); 100 push_up(root); 101 } 102 103 int n; 104 ll arr[4][maxn]; 105 int mx[4][maxn], mn[4][maxn]; 106 int px[4], pn[4]; 107 108 int main() { 109 n = read(); 110 for (int i = 1; i <= 3; ++i) { 111 for (int j = 1; j <= n; ++j) { 112 arr[i][j] = read(); 113 } 114 } 115 ll ans = 0; 116 for (int r = 1; r <= n; ++r) { 117 for (int i = 1; i <= 3; ++i) { 118 while (pn[i] && arr[i][mn[i][pn[i]]] >= arr[i][r]) { 119 update(1, 1, n, mn[i][pn[i] - 1] + 1, mn[i][pn[i]], arr[i][mn[i][pn[i]]], i); 120 --pn[i]; 121 } 122 mn[i][++pn[i]] = r; 123 update(1, 1, n, mn[i][pn[i] - 1] + 1, r, -arr[i][r], i); 124 125 while (px[i] && arr[i][mx[i][px[i]]] <= arr[i][r]) { 126 update(1, 1, n, mx[i][px[i] - 1] + 1, mx[i][px[i]], -arr[i][mx[i][px[i]]], i); 127 --px[i]; 128 } 129 mx[i][++px[i]] = r; 130 update(1, 1, n, mx[i][px[i] - 1] + 1, r, arr[i][r], i); 131 } 132 ans += tr[1][7]; 133 ans %= mod; 134 } 135 cout << (ans + mod) % mod << endl; 136 }