문제 DTOJ 번호 4123.에 솔루션 회사 전체를 "2019 겨울 캠프 그룹은 개선하기 위해"

에 오신 것을 환영합니다 내 Luogu 공간 .


[제목] 효과

서열을 가지며, 각각의 포인트에 대한 두개의 값이있다 \는 (a [I] \)\ (T [I] \) .

첫 번째 선택하면 \을 (내가 \) 포인트가 주어집니다 (A [내가] * t는 [ 내가] \) \ 기여하지만, 선택할 수 없습니다 ((\ A [i]를 -t [I], A [i]를 t [I]) \) + 범위 내에서 다른 포인트.

얻을 수 묻는 가장 큰 기여.


[설명]

세그먼트 트리 최적화 DP .

쉽게 발생할 오프라인 \ (DP \) \
(DP [I] = 최대 (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, 그것은 [\ \ 난]) 기록 및 답변의 최대 값.


[코드]

// 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