@atcoder - ドリンクハードとARC066F @コンテスト


@説明@

シーケンスT1、T2、... TNを考えると、あなたは、Tiの数、0を選択することができ(すなわち、選択されていない)から選択することができます。

あなたが定義した値=選択し、右の(Tを満たす数[L ... R]は、区間[L、R]を選択している) - (お好みのTiの合計)は、あなたができるだけ大きく重量が欲しいです。

Xiに変更さT [PI]は、最大重量はあなたが選択することができるかどうか尋ね、必ず尋ねM時間があります。

制約
。1 <= N、M <= 5,1。3 * ^ 10 <= Tiの<= 10 ^ 9、全てのTi <= 10 ^ 12の合計。
クエリごとに、満足1 <= Piの<= N、 1 <= Xiの<= 10 ^ 9。

入力
入力次の形式:
N
TlのT2 ... TN
M
P1のX1の
P2 X2

PM XM

出力
各問い合わせに対して、回答の出力。

サンプル入力1
5
1 1 1 1
2
3 2
3 10
サンプル出力1
9
2

@溶液@

Xiの後のT [PI]、パイが含まれて含まれたりしないようにどちらかの最後のオプションを変更することを検討してください。
1を選択し、パイ+ 1 ... N得られた最大値-そうでない場合は、あなただけの1 ...パイを必要としています。
西-含まれている場合、我々は、PI最適解は、最適解+ T [PI]を含む前処理を必要とします。

N ... [i]は私からほとんどの選択を示す第2グラム、[i]は1から表して最初のF ...私は、最適な回答を選択:要約すると、我々は三つのことに対処する必要があります優秀な答えは、第三H [i]は、私は最良の答えを選択する必要があります示しています。

最初のステップを考えると、の[i]はfを考えてみましょう。私はどちらかの[I-1] Fから選択から転送されていない、またはIを選択し、我々はすべて、Fへの貢献で強制選択I + 1 ...番号jを列挙することを我々は意味J [J] +([I + 1、間隔Jの数]で) - ([I + 1、 Tの値j]と)。
そして、によって接頭辞Sを前処理[I] = T [1 ] + T [2] + ... T [i]は、 より具体的な式を書くことが転送されてもよい:
\ [F [I] = \ MAX(F [ I-1]、\ MAX_ { 0 \ルJ <I}(F [J] + S [j]を- S [I] + \ FRAC {(IJ + 1)*(IJ)} {2}) )\]

その方程式を変更することが非常に少ない転送上記の最適化されたスロープは確かにスロープの最適化を見つけることができます。ここでは、具体的に書かれていません。
結論として、この式は、単調に増加する勾配であり、単調に増加するスロープ横軸の最適化(n)は単調スタック時間複雑性O行うことができます。
及びg [i]は、同様に処理することができます。ここでは特にそれについて話されていません。

今どのように需要H [i]を検討してください。+ G -列挙の方法は、iが右端点列挙R、寄与区間[L、R]の右側にL、Iを算出プラス[1 L] Fで最も激しい左左点である [R + 1]。
我々は非常に適切なパーティションを見つけ、最適化を検討するCDQ(実際には、私はそれがCDQ分割統治と呼ばれるべきではないことを知りませんが、より多くのように感じています)

間隔の中間の中間点を設定し、[左右]のために、我々は唯一満たす<= 1 <=ミッド<左検討 R <=右の時間間隔[L、R]寄与[L ... R]を。
=右から左まで、再帰[左、中間]および[中間+ 1は、右]、サブ問題を処理し続けます。

それに対処するには?[右、中間+ 1]回答として右点をすべての点の傾斜を最適化することにより得られる[右、中間+ 1]左から右へとスイープ;我々は、最初の[左、中間]は単調点スタックを添加し、次いで右から左への走査、TMP、更新されたH [X]とTMPの最大スイープX [X、右]を維持しつつ。
その後、今度は[中間+ 1は、右]単調スタック、アップデート[左、中間] hの値を加えました。このプロセスは、上記と同様である、それらを繰り返しません。

@acceptedコード@

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 300000;
const ll INF = (1LL<<60);
ll f[MAXN + 5], g[MAXN + 5], h[MAXN + 5];
ll S[MAXN + 5], T[MAXN + 5];
ll fk(int i) {return i;}
ll fx(int j) {return 2LL*j;}
ll fc(int i) {return 1LL*i*i + i - 2*S[i];}
ll fy(int j) {return 2*S[j] + f[j] - j + 1LL*j*j;}
double fslope(int p, int q) {return 1.0*(fy(q) - fy(p)) / (fx(q) - fx(p));}
ll gk(int i) {return -i;}
ll gx(int j) {return -2LL*j;}
ll gc(int i) {return 1LL*i*i - i + 2*S[i-1];}
ll gy(int j) {return -2*S[j-1] + g[j] + j + 1LL*j*j;}
double gslope(int p, int q) {return 1.0*(gy(q) - gy(p)) / (gx(q) - gx(p));}
int stk[MAXN + 5], tp;
int N, M;
void get_dp() {
    f[0] = 0; stk[tp = 1] = 0;
    for(int i=1;i<=N;i++) {
        while( tp > 1 && fk(i) >= fslope(stk[tp], stk[tp-1]) )
            tp--;
        f[i] = max(f[i - 1], fc(i) - fk(i)*fx(stk[tp]) + fy(stk[tp]));
        while( tp > 1 && fslope(i, stk[tp]) >= fslope(stk[tp], stk[tp-1]) )
            tp--;
        stk[++tp] = i;
    }
    g[N + 1] = 0; stk[tp = 1] = N + 1;
    for(int i=N;i>=1;i--) {
        while( tp > 1 && gk(i) >= gslope(stk[tp], stk[tp-1]) )
            tp--;
        g[i] = max(g[i + 1], gc(i) - gk(i)*gx(stk[tp]) + gy(stk[tp]));
        while( tp > 1 && gslope(i, stk[tp]) >= gslope(stk[tp], stk[tp-1]) )
            tp--;
        stk[++tp] = i;
    }
}
ll tmp[MAXN + 5];
void divide_conquer(int l, int r) {
    if( l == r ) {
        h[l] = f[l + 1] - 2*T[l] + g[r + 1] + 2;
        return ;
    }
    int mid = (l + r) >> 1;
    divide_conquer(l, mid);
    divide_conquer(mid + 1, r);
    stk[tp = 1] = l - 1;
    for(int i=l;i<mid;i++) {
        while( tp > 1 && fk(i) >= fslope(stk[tp], stk[tp-1]) )
            tp--;
        while( tp > 1 && fslope(i, stk[tp]) >= fslope(stk[tp], stk[tp-1]) )
            tp--;
        stk[++tp] = i;
    }
    for(int i=mid+1;i<=r;i++) {
        while( tp > 1 && fk(i) >= fslope(stk[tp], stk[tp-1]) )
            tp--;
        tmp[i] = fc(i) - fk(i)*fx(stk[tp]) + fy(stk[tp]) + g[i + 1];
    }
    ll p = -INF;
    for(int i=r;i>mid;i--) {
        p = max(p, tmp[i]);
        h[i] = max(h[i], p);
    }
    stk[tp = 1] = r + 1;
    for(int i=r;i>mid+1;i--) {
        while( tp > 1 && gk(i) >= gslope(stk[tp], stk[tp-1]) )
            tp--;
        while( tp > 1 && gslope(i, stk[tp]) >= gslope(stk[tp], stk[tp-1]) )
            tp--;
        stk[++tp] = i;
    }
    for(int i=mid;i>=l;i--) {
        while( tp > 1 && gk(i) >= gslope(stk[tp], stk[tp-1]) )
            tp--;
        tmp[i] = gc(i) - gk(i)*gx(stk[tp]) + gy(stk[tp]) + f[i - 1];
    }
    p = -INF;
    for(int i=l;i<=mid;i++) {
        p = max(p, tmp[i]);
        h[i] = max(h[i], p);
    }
}
int main() {
    scanf("%d", &N);
    for(int i=1;i<=N;i++)
        scanf("%lld", &T[i]), S[i] = S[i - 1] + T[i];
    get_dp(), divide_conquer(1, N);
    scanf("%d", &M);
    for(int i=1;i<=M;i++) {
        int P, X; scanf("%d%d", &P, &X);
        printf("%lld\n", max(f[P-1] + g[P+1], h[P] + 2*T[P] - 2*X)/2);
    }
}

@詳細@

Hは[i]は、iの値が含まれていなければならないし、それが初期化するとき、それは時間-INFに割り当てる必要があり、負であってもよいです。

今ARCを言っatcoder、ARCは涙の時代になっていません。

おすすめ

転載: www.cnblogs.com/Tiw-Air-OAO/p/11407452.html