会社全体「を改善するために2019年冬のキャンプ・グループ」問題DTOJ番号4123.へのソリューション

ようこそ私Luoguスペース


[タイトル]効果

配列を有し、各ポイントのための2つの値が存在する\([I] \)\(Tは、[I] \)

あなたが最初に選択した場合は、\を(私は\)ポイントが与えられます([I] * T [ i]が\)\ 貢献が、選択することはできません(([I] -t \ [i]は、[I] Tを+ [I])\)の範囲内の他のポイント。

取得することができる最大の貢献を求めました。


[説明]

セグメントツリーの最適化のDP

容易にオフラインで、発生\(DP \) \:
(DP [I] = MAX(DP [J] + A [I] * T [I])\) \(\(T + J [J]≦Iを)\ \&\&\(IT [I]≥j)\)

しかし、この時間は、効率が非常に良好であるので、この最適化を検討し\(DPの\を)

私たちは現在のためにことがわかった\(私は\)列挙\(J \)時から常に\(1 \)かかり、列挙を開始するには、\ \(DP [j]を \j∈[1、それ\ [Iを]] \)最大。

最大間隔、データ構造を変更するための単一のポイントを照会することができると考えてください。

しかし、しない範囲でも満たしている必要があり、すべてのポイントを取ることができます\(T + J [J]≦私は\)

また、この方程式の左側のみことがわかった\(j個\)私たちのに対し、\は(私は\)の順序の列挙です、それが現在の場合と言うことです\は(私は\)一定に撮影することができます(\ J \)は、その後、後に\(私は\)も取ることができている\(J \を)

したがって、それが必要なだけである唯一の新しい良い計算する必要が\(DP [J] \)\(I = J + T [ J] \)のようなデータ構造内に置かれたとき。

その後、上記の操作にそれぞれ問い合わせ、クエリー間隔\([1、IT [\ I] \) 記録及び回答の最大値。


[コード]

// output format !!
// long long !!
#include <bits/stdc++.h>
#define H puts("HYX")
#define ls (x<<1)
#define rs (x<<1|1)
using std::max;
typedef long long LL;
const int MAXN = 1000000+10;
struct DATA{int loc; LL dat;};

int n, t[MAXN], a[MAXN];
LL tre[MAXN*4], ans;
std::vector<DATA> tmp[MAXN];

int rd(){
    char c;while(!isdigit(c=getchar()));
    int x=c-'0';while(isdigit(c=getchar())) x=x*10+c-'0';
    return x;
}
void modify(int x, int l, int r, int p, LL v){
    if(l == r) return tre[x] = v, void();
    int mid = (l+r)>>1;
    if(p <= mid) modify(ls, l, mid, p, v);
    else modify(rs, mid+1, r, p, v);
    tre[x] = max(tre[ls], tre[rs]);
}
LL query(int x, int l, int r, int ql, int qr){
    if(ql<=l && r<=qr) return tre[x];
    int mid = (l+r)>>1; LL res = 0;
    if(ql <= mid) res = max(res, query(ls, l, mid, ql, qr));
    if(qr > mid) res = max(res, query(rs, mid+1, r, ql, qr));
    return res;
}
int main(){
//  freopen("fc.in", "r", stdin);
//  freopen("fc.out", "w", stdout);
    scanf("%d", &n);
    for(int i=1; i<=n; ++i) t[i] = rd();
    for(int i=1; i<=n; ++i) a[i] = rd();
    for(int i=1; i<=n; ++i){
        for(auto j=tmp[i].begin(); j!=tmp[i].end(); ++j) 
            modify(1, 1, n, (*j).loc, (*j).dat);
        LL dp = (i-t[i]>0?query(1, 1, n, 1, i-t[i]):0)+1ll*a[i]*t[i];
        if(i+t[i] <= n) tmp[i+t[i]].push_back((DATA){i, dp});
        if(dp > ans) ans = dp;
    }
    printf("%lld", ans);
    return 0;
}

私はゼロのバーストので、関数パラメータ内の長い長い!!を覚えている......

おすすめ

転載: www.cnblogs.com/bosswnx/p/10988181.html