セグメントツリー - [SP2916]あなたは、これらのクエリVに答えることができます

フェイス質問

あなたが与えられているシーケンス\(A_1、A_2、...、A_Nを\) \(| A [i]は| \当量10000、1 \当量N \の当量10000 \) )。次のようにクエリが定義されている:クエリ(X1、Y1、X2、Y2)= \(最大{a_iを+ A_ {I + 1} + ... + a_j; X_1 \の当量I \当量Y_1、X_2 \当量のJ \当量Y_2} \)\(X_1 \当量X_2、Y_1 \当量Y_2 \) 与えられた\(m個\)クエリ(\(1 \当量Mの\の当量10000 \) )、あなたのプログラムを出力しなければならないこれらのクエリの結果。

問題の意味

すべてのセクションは、左右端点で必要とされる([X_1、Y_1] \ \ ) と([X_2、Y_2] \) \ 最大連続サブセグメントの間隔と最大値

考え

1°2ばらばらの間隔


明白な答え、すなわち部の+ LMAX右部分、中間和と重ならないRMAX +間隔を残している:\([X_1、Y_1] .rmax + [Y_1、X_2] .SUM + [X_2、Y_2] .lmax \)

2度交差する2つのセクション


答えは3例があります
:①・すなわち分割交差部への答え、\([X_2、Y_1] .MAX \)
左部分の・②左解答ポイント範囲RMAX交差点は、交差点を左にして休息を取るにLMAX範囲は、その後、二回交差点ノード左マイナスに加え
、即ち:\([X_1、X_2] .rmax + [X_2、Y_2] X_2 .lmax-A_ {} \)
・③交点における正解部右部分、およびセクションの右側部分の交点を取る残りRMAX LMAX、そして二度交差点ノードを失った権利に加え
:すなわち\([Y_1、Y_2] .lmax + [X_1、Y_1] .rmax-Y_1 A_ {} \)

コード

/************************************************
*Author        :  lrj124
*Created Time  :  2019.09.27.21:55
*Mail          :  [email protected]
*Problem       :  spoj2916
************************************************/
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 10000 + 10;
struct seg { int l,r,sum,max; } tree[maxn<<2];
int T,n,q,a[maxn];
inline void pushup(int root) {
    tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
    tree[root].l = max(tree[root<<1].l,tree[root<<1|1].l+tree[root<<1].sum);
    tree[root].r = max(tree[root<<1|1].r,tree[root<<1].r+tree[root<<1|1].sum);
    tree[root].max = max(tree[root<<1].r+tree[root<<1|1].l,max(tree[root<<1].max,tree[root<<1|1].max));
}
inline void build(int l,int r,int root) {
    if (l == r) {
        tree[root] = { a[l],a[l],a[l],a[l] };
        return;
    }
    int mid = l+r>>1;
    build(l,mid,root<<1);
    build(mid+1,r,root<<1|1);
    pushup(root);
}
inline seg query(int l,int r,int ql,int qr,int root) {
    if (ql > qr) return {0,0,0,0};
    if (ql <= l && r <= qr) return tree[root];
    int mid = l+r>>1;
    if (mid >= qr) return query(l,mid,ql,qr,root<<1);
    if (ql > mid) return query(mid+1,r,ql,qr,root<<1|1);
    seg lson = query(l,mid,ql,qr,root<<1),rson = query(mid+1,r,ql,qr,root<<1|1),ans;
    ans = { max(lson.l,rson.l+lson.sum),max(rson.r,lson.r+rson.sum),rson.sum+lson.sum,max(lson.r+rson.l,max(lson.max,rson.max)) };
    return ans;
}
inline int solve(int l1,int r1,int l2,int r2) {
    if (r1 < l2) return query(1,n,l1,r1,1).r+query(1,n,r1+1,l2-1,1).sum+query(1,n,l2,r2,1).l;
    int ans = query(1,n,l2,r1,1).max;
    if (l1 < l2) ans = max(ans,query(1,n,l1,l2,1).r+query(1,n,l2,r2,1).l-a[l2]);
    if (r2 > r1) ans = max(ans,query(1,n,l1,r1,1).r+query(1,n,r1,r2,1).l-a[r1]);
    return ans;
}
int main() {
    for (scanf("%d",&T);T--;) {
        memset(tree,0,sizeof(tree));
        scanf("%d",&n);
        for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
        build(1,n,1);
        for (scanf("%d",&q);q--;) {
            int l1,r1,l2,r2; scanf("%d%d%d%d",&l1,&r1,&l2,&r2);
            printf("%d\n",solve(l1,r1,l2,r2));
        }
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/lrj124/p/11681318.html