zoukankan      html  css  js  c++  java
  • 极差 牛客-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("*********
    ")
     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 }
  • 相关阅读:
    取得窗口大小和窗口位置兼容所有浏览器的js代码
    一个简单易用的导出Excel类
    如何快速启动chrome插件
    网页表单设计案例
    Ubuntu下的打包解包
    The source file is different from when the module was built. Would you like the debugger to use it anyway?
    FFisher分布
    kalman filter
    Group delay Matlab simulate
    24位位图格式解析
  • 原文地址:https://www.cnblogs.com/zhang-Kelly/p/12905572.html
Copyright © 2011-2022 走看看