BZOJ 4826: [Hnoi2017]影魔

两种贡献不会同时产生,分开考虑两种贡献
\(pre_i\)\(i\) 之前第一个大于 \(a_i\) 的数,\(suf_i\)\(i\) 之后第一个大于 \(a_i\) 的数,可以单调栈预处理出来
对于第一种贡献

  1. \(i\) 会对 \(i + 1\) 产生 \(p_1\) 的贡献
  2. \(i\) 会对 \(pre_i\)\(suf_i\) 这个点对产生 \(p_1\) 的贡献

相当于对于横坐标 \(pre_i\),纵坐标 \(suf_i\) 处有 \(p_1\) 的贡献

对于第二种贡献
因为满足单调性,而且中间这个数是最大的,那么大于它的端点肯定是 \(pre\) 或者 \(suf\) 之一

  1. 左端点为 \(pre_i\),那么对 \([i + 1, suf_i-1]\)\(p_2\) 的贡献
  2. 右端点为 \(suf_i\),那么对 \([pre_i+1, i - 1]\)\(p_2\) 的贡献

相当于横坐标上 纵坐标为一个区间有 \(p_2\) 的贡献
查询就相当于二维数点
可以主席树处理也可以扫描线+树状数组
后者常数较小
主席树需要标记永久化支持区间修改

#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define lp tree[p].l
#define rp tree[p].r
#define lq tree[q].l
#define rq tree[q].r
#define mid ((l + r) >> 1)
namespace IO {
    const int MAXSIZE = 1 << 20;
    char buf[MAXSIZE], *p1, *p2;
    #define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) ? EOF : *p1++)
    inline void read() {}
    template<typename T, typename ... T2>
    inline void read(T &x, T2 &... oth) {
        x = 0; T f = 1; char ch = gc();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = gc(); }
        while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = gc(); }
        x *= f;
        read(oth...);
    }
}
const int N = 2e5 + 7;

struct Seg {
    struct Node {
        int l, r, tag;
        ll sum;
    } tree[N * 60];
    int tol;
    void update(int &p, int q, int l, int r, int x, int y, int v) {
        tree[p = ++tol] = tree[q];
        tree[p].sum += 1LL *  (std::min(y, r) - std::max(l, x) + 1) * v;
        if (x <= l && y >= r) {
            tree[p].tag += v;
            return;
        }
        if (x <= mid) update(lp, lq, l, mid, x, y, v);
        if (y > mid) update(rp, rq, mid + 1, r, x, y, v);
    }
    ll query(int p, int l, int r, int x, int y) {
        if ((x <= l && y >= r) || (!p)) return tree[p].sum;
        ll ans = 1LL * (std::min(y, r) - std::max(l, x) + 1) * tree[p].tag;
        if (x <= mid) ans += query(lp, l, mid, x, y);
        if (y > mid) ans += query(rp, mid + 1, r, x, y);
        return ans;
    }
    ll query(int p, int q, int l, int r, int x, int y) {
        return query(p, l, r, x, y) - query(q, l, r, x, y);
    }
} seg;

int n, m, p1, p2;
int a[N], pre[N], suf[N], st[N], top;
int root[N];

struct Node {
    int l, r, v;
    Node() {}
    Node(int l, int r, int v): l(l), r(r), v(v) {}
};
std::vector<Node> vec[N];

int main() {
    IO::read(n, m, p1, p2);
    for (int i = 1; i <= n; i++)
        IO::read(a[i]);
    st[top = 1] = 0;
    for (int i = 1; i <= n; i++) {
        while (top > 1 && a[st[top]] < a[i]) top--;
        pre[i] = st[top];
        st[++top] = i;
    }
    st[top = 1] = n + 1;
    for (int i = n; i >= 1; i--) {
        while (top > 1 && a[st[top]] < a[i]) top--;
        suf[i] = st[top];
        st[++top] = i;
    }
    for (int i = 1; i <= n; i++) {
        if (i < n) vec[i].pb(Node(i + 1, i + 1, p1));
        if (pre[i] > 0 && suf[i] <= n) vec[suf[i]].pb(Node(pre[i], pre[i], p1));
        if (pre[i] + 1 < i && suf[i] <= n) vec[suf[i]].pb(Node(pre[i] + 1, i - 1, p2));
        if (suf[i] - 1 > i && pre[i]) vec[pre[i]].pb(Node(i + 1, suf[i] - 1, p2));
    }
    for (int i = 1; i <= n; i++) {
        root[i] = root[i - 1];
        for (int j = 0; j < vec[i].size(); j++) {
            seg.update(root[i], root[i], 1, n, vec[i][j].l, vec[i][j].r, vec[i][j].v);
        }
    }
    for (int l, r; m--; ) {
        IO::read(l, r);
        printf("%lld\n", seg.query(root[r], root[l - 1], 1, n, l, r));
    }
    return 0;
}
#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define mid ((l + r) >> 1)
#define lp p << 1
#define rp p << 1 | 1
namespace IO {
    const int MAXSIZE = 1 << 20;
    char buf[MAXSIZE], *p1, *p2;
    #define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) ? EOF : *p1++)
    inline void read() {}
    template<typename T, typename ... T2>
    inline void read(T &x, T2 &... oth) {
        x = 0; T f = 1; char ch = gc();
        while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = gc(); }
        while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = gc(); }
        x *= f;
        read(oth...);
    }
}
const int N = 2e5 + 7;

int n, m, p1, p2;
int a[N], pre[N], suf[N], st[N], top;
ll ans[N];

struct BIT {
    int c1[N];
    ll c2[N];
    inline void clear() {
        memset(c1, 0, sizeof(int) * (n + 1));
        memset(c2, 0, sizeof(ll) * (n + 1));
    }
    inline int lowbit(int x) { return x & -x; }
    inline void add(int x, int v) {
        for (int i = x; i <= n; i += lowbit(i)) {
            c1[i] += v;
            c2[i] += 1LL * x * v;
        }
    }
    inline void add(int l, int r, int v) {
        add(l, v); add(r + 1, -v);
    }
    inline ll query(int x) {
        ll ans = 0;
        for (int i = x; i; i -= lowbit(i)) {
            ans += 1LL * (x + 1) * c1[i] - c2[i];
        }
        return ans;
    }
    inline ll query(int l, int r) {
        return query(r) - query(l - 1);
    }
} bit;

struct Node {
    int l, r, v;
    Node() {}
    Node(int l, int r, int v): l(l), r(r), v(v) {}
};
struct Query {
    int l, r, id;
} Q[N];
bool cmp1(const Query &a, const Query &b) {
    return a.r < b.r;
}
bool cmp2(const Query &a, const Query &b) {
    return a.l > b.l;
}

std::vector<Node> vec[N], vec2[N];

int main() {
    IO::read(n, m, p1, p2);
    for (int i = 1; i <= n; i++)
        IO::read(a[i]);
    st[top = 1] = 0;
    for (int i = 1; i <= n; i++) {
        while (top > 1 && a[st[top]] < a[i]) top--;
        pre[i] = st[top];
        st[++top] = i;
    }
    st[top = 1] = n + 1;
    for (int i = n; i >= 1; i--) {
        while (top > 1 && a[st[top]] < a[i]) top--;
        suf[i] = st[top];
        st[++top] = i;
    }
    for (int i = 1; i <= n; i++) {
        if (i < n) vec2[i].pb(Node(i + 1, i + 1, p1));
        if (pre[i] > 0 && suf[i] <= n) vec[suf[i]].pb(Node(pre[i], pre[i], p1));
        if (pre[i] + 1 < i && suf[i] <= n) vec[suf[i]].pb(Node(pre[i] + 1, i - 1, p2));
        if (suf[i] - 1 > i && pre[i]) vec2[pre[i]].pb(Node(i + 1, suf[i] - 1, p2));
    }
    for (int i = 1; i <= m; i++)
        IO::read(Q[i].l, Q[i].r), Q[i].id = i;
    std::sort(Q + 1, Q + 1 + m, cmp1);
    int cur = 1;
    for (int i = 1; i <= m; i++) {
        while (cur <= n && cur <= Q[i].r) {
            for (int j = 0; j < vec[cur].size(); j++)
                bit.add(vec[cur][j].l, vec[cur][j].r, vec[cur][j].v);
            cur++;
        }
        ans[Q[i].id] += bit.query(Q[i].l, Q[i].r);
    }
    std::sort(Q + 1, Q + 1 + m, cmp2);
    bit.clear();
    cur = n;
    for (int i = 1; i <= m; i++) {
        while (cur && cur >= Q[i].l) {
            for (int j = 0; j < vec2[cur].size(); j++)
                bit.add(vec2[cur][j].l, vec2[cur][j].r, vec2[cur][j].v);
            cur--;
        }
        ans[Q[i].id] += bit.query(Q[i].l, Q[i].r);
    }
    for (int i = 1; i <= m; i++)
        printf("%lld\n", ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12312364.html