极差 牛客-16736(单调栈,线段树)

题意:

给出三个长度为$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("*********\n")
 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 }

 

posted @ 2020-05-17 16:05  Big-Kelly  阅读(317)  评论(0编辑  收藏  举报