WuliWuliiii
凤兮凤兮归故乡 遨游四海求其凰

题目链接

题意:如标题所示,给出N个数,以及M次查询,查询[L, R]区间内连续和小于等于U的最大值。

思路:很明显的,想到了一个做法,我们可以去对于U值作为一个时间刻度,进行升序,同时,一共有N * (N + 1) / 2个连续和,发现这么多连续和,其实不算多啊,我们对于每个连续和的权值存下来,并且维护它对应的L和R点,于是乎,我们实际上就将问题变成了求解二维区间(L, L)至二维区间(R, R)中的最大值的问题了,而实际上对于一个值,它会放置在(Li, Ri)的位置上。这个带插入的求二维区间最大值的问题,我们可以认为它是一个复杂度为(N * N * log * log + M * log * log)的问题,简单的来说,就是树套树问题。

  但是,很容易发现的一点就是,时间卡的真的是紧,我尝试了不去sort,不离散化等方法,对于这个复杂度的做法,最后始终得到了TLE5的结果,看来得利用更小常数的做法来解决了。更小常数?二维树状数组?!

  好家伙,还真是二维树状数组,经过大佬liangs333的一番教导,我明白了,如果现在有这样的一个内包含和外包含的关系[l, r]和外包含的[L, R]我们有L ≤ l ≤ r ≤ R。这个东西变种一下,因为两维均是单独成立的,所以我们对“L”这一维,进行逆处理。我们令L = N - L + 1,也就是将他们都反过来了,好家伙,这样就满足了r ≤ R,且(N - l + 1) ≤ (N - L + 1),变成了两个同时的包含关系,于是,变成了二维前缀和,于是此题虽然复杂度没有变化,但是却有了更小的常数,问题引刃而解。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define LNF 0x3f3f3f3f3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define pii pair<int, int>
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e3 + 5, maxM = 2e5 + 7;
int N, M, tot;
ll a[maxN], pre[maxN], ans[maxM];
struct node
{
    int l, r; ll v; int id;
    node(int a=0, int b=0, ll c=0, int d=0):l(a), r(b), v(c), id(d) {}
    friend bool operator < (node e1, node e2)
    { return e1.v == e2.v ? e1.id < e2.id : e1.v < e2.v; }
} t[maxN * maxN / 2 + maxM];
ll tree[maxN][maxN];
void update(int x, int y, ll v)
{
    for(int i = x; i <= N; i += lowbit(i))
        for(int j = y; j <= N; j += lowbit(j))
            tree[i][j] = max(tree[i][j], v);
}
ll query(int x, int y)
{
    ll ans = -LNF;
    for(int i = x; i; i -= lowbit(i))
        for(int j = y; j; j -= lowbit(j))
            ans = max(ans, tree[i][j]);
    return ans;
}
int main()
{
    scanf("%d%d", &N, &M);
    for(int i = 1; i <= N; i ++) { scanf("%lld", &a[i]); pre[i] = pre[i - 1] + a[i]; }
    for(int l = 1; l <= N; l ++) for(int r = l; r <= N; r ++)
        t[++ tot] = node(l, r, pre[r] - pre[l - 1], 0);
    ll tmp;
    for(int i = 1, l, r; i <= M; i ++)
    {
        scanf("%d%d%lld", &l, &r, &tmp);
        t[++ tot] = node(l, r, tmp, i);
    }
    sort(t + 1, t + tot + 1);
    for(int i = 1; i <= N; i ++) for(int j = 1; j <= N; j ++) tree[i][j] = -LNF;
    for(int i = 1; i <= tot; i ++)
    {
        if(t[i].id)
        {
            ans[t[i].id] = query(N - t[i].l + 1, t[i].r);
        }
        else
        {
            update(N - t[i].l + 1, t[i].r, t[i].v);
        }
    }
    for(int i = 1; i <= M; i ++)
    {
        if(ans[i] > -LNF) printf("%lld\n", ans[i]);
        else printf("NONE\n");
    }
    return 0;
}

 

posted on 2021-04-01 15:01  唔哩Wulili  阅读(64)  评论(0编辑  收藏  举报