結果

問題 No.776 A Simple RMQ Problem
ユーザー KKT89KKT89
提出日時 2021-06-20 13:01:01
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 2,693 bytes
コンパイル時間 2,669 ms
コンパイル使用メモリ 218,940 KB
実行使用メモリ 11,864 KB
最終ジャッジ日時 2024-06-22 22:27:51
合計ジャッジ時間 6,636 ms
ジャッジサーバーID
(参考情報)
judge5 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 WA -
testcase_02 WA -
testcase_03 WA -
testcase_04 WA -
testcase_05 WA -
testcase_06 WA -
testcase_07 WA -
testcase_08 WA -
testcase_09 AC 30 ms
11,596 KB
testcase_10 WA -
testcase_11 AC 75 ms
11,560 KB
testcase_12 WA -
testcase_13 AC 96 ms
11,564 KB
testcase_14 AC 97 ms
11,584 KB
testcase_15 WA -
testcase_16 AC 95 ms
11,796 KB
testcase_17 WA -
testcase_18 AC 77 ms
11,644 KB
testcase_19 AC 108 ms
11,576 KB
testcase_20 WA -
testcase_21 AC 108 ms
11,576 KB
testcase_22 WA -
testcase_23 WA -
testcase_24 WA -
testcase_25 AC 29 ms
6,944 KB
testcase_26 AC 74 ms
11,524 KB
testcase_27 AC 66 ms
11,524 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
    return (ull)rng() % B;
}

// 最大部分列をセグ木で求める
struct monoid{
    ll ans; // その区間における最大部分列
    ll L,R; // 左(右)側累積和最大値
    ll sum; // 区間の総和
    monoid(){
        ans=-1e18;
        L=R=-1e18;
        sum=0;
    }
    monoid(ll x){
        ans=x;
        L=R=max(x,0LL);
        sum=x;
    }
};
monoid f(monoid A,monoid B){
    monoid res;
    res.L=max(A.L,A.sum+B.L);
    res.R=max(B.R,B.sum+A.R);
    res.sum=A.sum+B.sum;
    res.ans=max(A.ans,B.ans);
    res.ans=max(res.ans,A.R+B.L);
    return res;
}
struct SegmentTree{
    int sz;
    vector<monoid> seg;
    SegmentTree(int n){
        sz=1;
        while(sz<n)sz<<=1;
        seg.resize(2*sz);
    }
    void set(int i,ll x){
        seg[i+sz]=monoid(x);
    }
    void init(){
        for(int i=sz-1;i>0;i--){
            seg[i]=f(seg[2*i],seg[2*i+1]);
        }
    }
    void update(int k,ll x){
        k+=sz;
        seg[k]=monoid(x);
        while(k>>=1){
            seg[k]=f(seg[2*k],seg[2*k+1]);
        }
    }
    monoid query(int l,int r){
        monoid L,R;
        for(l+=sz,r+=sz;l<r;l>>=1,r>>=1){
            if(l&1) L=f(L,seg[l++]);
            if(r&1) R=f(seg[--r],R);
        }
        return f(L,R);
    }
    ll query(int l1,int r1,int l2,int r2){
        // [l1,r1), [l2,r2)
        if(r1<=l2){
            return query(l1,r1-1).R+query(r1-1,l2+1).sum+query(l2+1,r2).L;
        }
        else{ // l2<r1
            ll res=-1e18;
            // l2を含む場合
            res=max(res,query(l1,l2).R+query(l2+1,r2).L+seg[l2+sz].sum);
            // r1-1を含む場合
            res=max(res,query(l1,r1-1).R+query(r1,r2).L+seg[r1-1+sz].sum);
            // [l2,r1)の場合
            res=max(res,query(l2,r1).ans);
            return res;
        }
    }
};

int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n,q; cin >> n >> q;
    SegmentTree seg(n);
    for(int i=0;i<n;i++){
        ll a; cin >> a;
        seg.set(i,a);
    }
    seg.init();
    while(q--){
        string op; cin >> op;
        if(op=="set"){
            int i,x; cin >> i >> x;
            seg.update(i-1,x);
        }
        else{
            // 問題文と変数の対応が変わってます
            int l1,l2,r1,r2; cin >> l1 >> r1 >> l2 >> r2;
            l1--; l2--;
            l2=max(l2,l1);
            r1=min(r1,r2);
            printf("%lld\n",seg.query(l1,r1,l2,r2));
        }
    }
}
0