Code Chef JUMP(递推+树状数组+李超线段树)

\(JUMP\)

很容易写出转移柿子

\[f_i=\min_{p_j<p_i}\{(h_i-h_j)^2+f_j\}+w_i \]

\(\min\)里面的东西展开一下

\[f_j=\min_{p_j<p_i}\{-2h_jh_i+h_j^2+f_j\}+h_i^2+w_i \]

里面的\(\min\)是一个一次函数

首先这是一个类似于区间查询的东西,我们可以用树状数组

里面查询的东西是一个最小值,也就是说我们要资瓷插入一次函数并求最小值,超哥线段树就行了

所以这其实是个树套树,不过树状数组套什么都挺好写就是了

话说动态凸包好像比超哥线段树快很多?可为啥我写动态凸包好慢啊……李超线段树快多了……

李超线段树代码

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
typedef long long ll;
const int N=3e5+5,M=2e6+5;const ll inf=(1ll<<60);
struct node;typedef node* ptr;
struct node{
	ptr lc,rc;ll k,b,lv,rv;bool flag;
	inline void ins(R ll kk,R ll bb,R int l,R int r){k=kk,b=bb,lv=l*k+b,rv=r*k+b,flag=1;}
	inline ll calc(R int x){return k*x+b;}
}e[M],*rt[N],*pp=e+1;
inline ptr newnode(){return pp->lc=pp->rc=e,pp++;}
ll b,k,bb,kk,res,f[N];int p[N],h[N],w[N],n,mx;
void query(ptr p,int l,int r,int x){
	cmin(res,p->calc(x));if(p==e||l==r)return;
	int mid=(l+r)>>1;
	x<=mid?query(p->lc,l,mid,x):query(p->rc,mid+1,r,x);
}
void update(ptr &p,int l,int r){
	if(p==e)p=newnode();if(!p->flag)return p->ins(k,b,l,r),void();
	int mid=(l+r)>>1;ll lv=k*l+b,rv=k*r+b;
	if(lv>=p->lv&&rv>=p->rv)return;
	if(lv<=p->lv&&rv<=p->rv)return p->ins(k,b,l,r),void();
	double x=(b-p->b)/(p->k-k);
	if(lv<=p->lv){
		if(x<=mid)update(p->lc,l,mid);
			else kk=p->k,bb=p->b,p->ins(k,b,l,r),k=kk,b=bb,update(p->rc,mid+1,r);
	}else{
		if(x<=mid)kk=p->k,bb=p->b,p->ins(k,b,l,r),k=kk,b=bb,update(p->lc,l,mid);
			else update(p->rc,mid+1,r);
	}
}
inline void upd(R int x,R ll kk,R ll bb){for(;x<=n;x+=x&-x)k=kk,b=bb,update(rt[x],1,mx);}
inline void query(R int x,R int c){res=inf;for(;x;x-=x&-x)query(rt[x],1,mx,c);}
int main(){
//	freopen("testdata.in","r",stdin);
	n=read();
	fp(i,1,n)p[i]=read();
	fp(i,1,n)w[i]=read();
	fp(i,1,n)h[i]=read(),cmax(mx,h[i]);
	fp(i,1,n)rt[i]=e;e->b=inf;
	f[1]=w[1],upd(p[1],-(h[1]<<1),f[1]+1ll*h[1]*h[1]);
	fp(i,2,n){
		R int H=h[i];query(p[i]-1,H);
		f[i]=res+1ll*H*H+w[i];
		upd(p[i],-(H<<1),f[i]+1ll*H*H);
	}
	printf("%lld\n",f[n]);
	return 0;
}

动态凸包代码

//minamoto
#include<bits/stdc++.h>
#define R register
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
typedef long long ll;
const int N=3e5+5;const ll inf=(1ll<<60);
ll res,f[N];int p[N],h[N],w[N],n,mx;bool qwq;
struct Line{
	ll k,b;mutable ll p;
	inline Line(R ll kk,R ll bb,R ll pp){k=kk,b=bb,p=pp;}
	inline bool operator <(const Line &b)const{return qwq?p<b.p:k>b.k;}
};
struct node;typedef multiset<Line>::iterator IT;
struct node{
	multiset<Line>s;
	bool inter(IT itl,IT itr){
		if(itr==s.end())return itl->p=inf,0;
		if(itl->k==itr->k)itl->p=itl->b>itr->b?-inf:inf;
			else itl->p=(itr->b-itl->b)/(itl->k-itr->k);
		return itl->p>=itr->p;
	}
	void ins(ll k,ll b){
		IT it,z=s.insert(Line(k,b,0)),y=z++,x=y;
		for(;inter(y,z);it=z,++z,s.erase(it));
		if(x!=s.begin()&&inter(--x,y))it=y,++y,s.erase(it),inter(x,y);
		for(;(y=x)!=s.begin()&&(--x)->p>=y->p;it=y,++y,s.erase(it),inter(x,y));
	}
	void query(R int x){
		qwq=1;IT it=s.lower_bound(Line(0,0,x));qwq=0;
		cmin(res,it==s.end()?inf:it->k*x+it->b);
	}
}s[N];
inline void upd(R int x,R ll k,R ll b){for(;x<=n;x+=x&-x)s[x].ins(k,b);}
inline void query(R int x,R int c){res=inf;for(;x;x-=x&-x)s[x].query(c);}
int main(){
//	freopen("testdata.in","r",stdin);
	n=read();
	fp(i,1,n)p[i]=read();
	fp(i,1,n)w[i]=read();
	fp(i,1,n)h[i]=read();
	f[1]=w[1],upd(p[1],-(h[1]<<1),f[1]+1ll*h[1]*h[1]);
	fp(i,2,n){
		R int H=h[i];query(p[i]-1,H);
		f[i]=res+1ll*H*H+w[i];
		upd(p[i],-(H<<1),f[i]+1ll*H*H);
	}
	printf("%lld\n",f[n]);
	return 0;
}
posted @ 2019-04-18 22:31  bztMinamoto  阅读(238)  评论(0编辑  收藏  举报
Live2D