zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",f[n]);
    	return 0;
    }
    
  • 相关阅读:
    vim/vi——\n只能被替换或删除 \r只能用来插入或替换
    程序算法与人生选择【转】
    【R】大型机Linux系统安装R及bsub提交R任务
    Mothur 命令手册Mothur命令中文解释(一)
    集群与分布式的区别
    【R】Linux安装R语言包(Installing R packages on Linux)
    Android TableLayout 常用的属性介绍及演示
    handler.obtainMessage()理解
    利用sax处理xml(推荐)
    Android 的权限设置大全3
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10732874.html
Copyright © 2011-2022 走看看