에 오신 것을 환영합니다 내 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;
}