[CodeChef Jump]Jump mission
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CodeChef Jump]Jump mission相关的知识,希望对你有一定的参考价值。
Jump mission
题解
简单树套树。
首先看到这道题,我们很容易想到
d
p
dp
dp。
设
d
p
i
dp_{i}
dpi表示选择跳到了第
i
i
i座山时总的消耗能量的最小值,容易得到
d
p
dp
dp转移式,
d
p
i
=
min
j
<
i
∧
p
j
<
p
i
(
d
p
j
+
(
h
i
−
h
j
)
2
+
a
i
)
=
min
j
<
i
∧
p
j
<
p
i
(
d
p
j
+
h
j
2
−
2
h
i
h
j
)
+
h
i
2
+
a
i
dp_{i}=\\min_{j<i\\wedge p_{j}<p_{i}}\\left(dp_{j}+(h_{i}-h_{j})^2+a_{i}\\right)=\\min_{j<i\\wedge p_{j}<p_{i}}\\left(dp_{j}+h_{j}^2-2h_{i}h_{j}\\right)+h_{i}^2+a_{i}
dpi=j<i∧pj<pimin(dpj+(hi−hj)2+ai)=j<i∧pj<pimin(dpj+hj2−2hihj)+hi2+ai
很明显,括号中间的式子是一个一次函数,我们可以考虑通过李超线段树对其进行维护。
但外面要同时满足两个要求,我们该怎么处理呢?
树套树,我们可以同时给外面加一个树状数组,维护
p
p
p的区间内的函数。
当然,这样就要动态开点了。
查询就查询前缀区间的每棵树上该位置的最大值。
时间复杂度显然是 O ( n log 2 n ) O\\left(n\\log^2n\\right) O(nlog2n)。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;
#define MAXN 300005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
typedef long long LL;
typedef unsigned long long uLL;
const LL INF=0x3f3f3f3f3f3f3f3f;
const int mo=1e9+7;
const int inv2=499122177;
const int jzm=2333;
const int zero=10000;
const int lim=30000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,LL> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){if(x<0){x=(~x)+1;putchar('-');}if(x>9)print(x/10);putchar(x%10+'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,tot,root[MAXN],totb;LL dp[MAXN],p[MAXN],a[MAXN],h[MAXN],ans,b[MAXN];
struct line{
LL k,b;line(){k=0;b=INF;}
line(LL K,LL B){k=K;b=B;}
LL ask(int x){return 1ll*x*k+b;}
};
struct node{int lson,rson;line p;}tr[MAXN*200];
void modify(int &rt,int l,int r,line aw){
int mid=l+r>>1;if(!rt)rt=++tot;
if(aw.ask(b[mid])<tr[rt].p.ask(b[mid]))swap(aw,tr[rt].p);if(l==r)return ;
if(aw.ask(b[l])<tr[rt].p.ask(b[l]))modify(tr[rt].lson,l,mid,aw);
if(aw.ask(b[r])<tr[rt].p.ask(b[r]))modify(tr[rt].rson,mid+1,r,aw);
}
LL query(int rt,int l,int r,int ai){
if(l>r||l>ai||r<ai)return INF;int mid=l+r>>1;
LL res=tr[rt].p.ask(b[ai]);if(l==r)return res;
if(ai<=mid)res=min(res,query(tr[rt].lson,l,mid,ai));
if(ai>mid)res=min(res,query(tr[rt].rson,mid+1,r,ai));
return res;
}
void insert(int pos,line p){while(pos<=n){modify(root[pos],1,totb,p);pos+=lowbit(pos);}}
LL ask(int pos,LL x){
int t=lower_bound(b+1,b+totb+1,x)-b;LL res=INF;
while(pos){res=min(res,query(root[pos],1,totb,t));pos-=lowbit(pos);}
return res;
}
signed main(){
read(n);
for(int i=1;i<=n;i++)read(p[i]);
for(int i=1;i<=n;i++)read(a[i]);dp[1]=a[1];
for(int i=1;i<=n;i++)read(h[i]),b[++totb]=h[i];
sort(b+1,b+totb+1);totb=unique(b+1,b+totb+1)-b-1;
for(int i=1;i<=n;i++){
if(i>1)dp[i]=ask(p[i],h[i])+a[i]+h[i]*h[i];
insert(p[i],line(-h[i]-h[i],dp[i]+h[i]*h[i]));
}
printf("%lld\\n",dp[n]);
return 0;
}
谢谢!!!
以上是关于[CodeChef Jump]Jump mission的主要内容,如果未能解决你的问题,请参考以下文章
China Jump Start-Preparation Of Car Jump Starter