gym102920I Stock Aalysis (2020-2021 ACM-ICPC, Asia Seoul Regional Contest) 三维偏序

题意

给一个长度为(n)的数组(a)(m)次询问,每次询问([S_i,E_i])中的子串和不超过(U_i)的最大值是多少。

思路

显然,可以发现是一个三位偏序题。询问(max{sum[l,r] | [-l,r,sum[l,r]]le[-S_i,E_i,U_i]})

然后就有多种方法,可以分块+树状数组(O(sqrt{n}*logn*m+logn*n^2+(n^2+m)log(n^2+m))),询问+插入+排序),也可以用二维树状数组(O((n^2+m)log^2n+(n^2+m)log(n^2+m)))),也可以cdq分治((O((n^2+m)*log(n^2+m)*logn+(n^2+m)log(n^2+m))))+卡常。。

代码

cdq分治

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int maxn = 2e3 + 5;
const int maxm = 2e5 + 5;
const ll inf = 1e18;
int a[maxn];
ll sum[maxn];
int s[maxm], e[maxm];
ll u[maxm];

struct IO{
#define MAXSIZE (1 << 20)
#define isdigit(x) (x >= '0' && x <= '9')
    char buf[MAXSIZE], *p1, *p2;
    IO() : p1(buf), p2(buf) {}
    inline char gc(){
        if (p1 == p2)
            p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin);
        return p1 == p2 ? ' ' : *p1++;
    }
    inline bool blank(char ch){
        return ch == ' ' || ch == '
' || ch == '
' || ch == '	';
    }
    template <class T>
    inline void read(T &x){
        bool sign = 0;
        x = 0;
        char ch = gc();
        for (; !isdigit(ch); ch = gc())
            if (ch == '-')
                sign = 1;
        for (; isdigit(ch); ch = gc())
            x = x * 10 + (ch - '0');
        if (sign)
            x = -x;
    }
} io;

struct Q{
    int l, r;
    ll val;
    int id;
} q[maxm + maxn * maxn], tmp[maxm + maxn * maxn];
int qcnt;
ll ans[maxm];

void cmax(ll &x, ll y){
    if (y > x)
        x = y;
}

struct Bit{
    ll data[maxn];

    Bit(){
        fill(data, data + maxn, -inf);
    }

    void insert(int pos, ll val){
        for (; pos < maxn; pos += (pos & -pos))
            cmax(data[pos], val);
    }
    void clear(int pos){
        for (; pos < maxn; pos += (pos & -pos))
            data[pos] = -inf;
    }
    ll max(int pos){
        ll ans = -inf;
        for (; pos > 0; pos -= (pos & -pos))
            cmax(ans, data[pos]);
        return ans;
    }
} bit;

void cdq(int l, int r)
{
    if (l == r)
        return;
    int mid = (l + r) / 2;
    cdq(l, mid);
    cdq(mid + 1, r);

    int id = l;
    vector<int> cl;
    for (int i = l, j = mid + 1; i <= mid || j <= r;)
    {
        if (j > r || i <= mid && q[i].l <= q[j].l)
        {
            tmp[id++] = q[i];
            if (q[i].id == 0)
            {
                cl.push_back(q[i].r);
                bit.insert(q[i].r, q[i].val);
            }
            i++;
        }
        else
        {
            tmp[id++] = q[j];
            if (q[j].id)
                cmax(ans[q[j].id], bit.max(q[j].r));
            j++;
        }
    }
    for (int i = l; i <= r; i++)
        q[i] = tmp[i];
    for (int r : cl)
        bit.clear(r);
}

int main()
{
    int n, m;
    io.read(n);
    io.read(m);
    for (int i = 1; i <= n; i++)
    {
        io.read(a[i]);
        sum[i] = sum[i - 1] + a[i];
    }
    for (int i = 1; i <= m; i++)
    {
        io.read(s[i]);
        io.read(e[i]);
        io.read(u[i]);
        q[++qcnt] = {-s[i], e[i], u[i], i};
        ans[i] = -inf;
    }

    for (int i = 1; i <= n; i++)
        for (int j = i; j <= n; j++)
            q[++qcnt] = {-i, j, sum[j] - sum[i - 1], 0};

    sort(q + 1, q + qcnt + 1, [](Q x, Q y) {
        if (x.val != y.val)
            return x.val < y.val;
        else if (x.l != y.l)
            return x.l < y.l;
        else if (x.r != y.r)
            return x.r < y.r;
        else
            return x.id < y.id;
    });
    cdq(1, qcnt);
    for (int i = 1; i <= m; i++)
    {
        if (ans[i] == -inf)
            printf("NONE
");
        else
            printf("%lld
", ans[i]);
    }

    return 0;
}
原文地址:https://www.cnblogs.com/intmian/p/14621585.html