zoukankan      html  css  js  c++  java
  • P7480 Reboot from Blue(cdq 分治优化 dp)

    发现题解里面没有纯(cdq)做法,这里提供一下

    首先把所有加油站按(c)排序,容易得到

    [f[i] = min(f[j] + c[i] * ∣x[i]-x[j]|) ]

    表示从(j ightarrow i)的一次转移

    f[i]表示(i ightarrow End)的最小花费

    显然复杂度是(O(n^2))的,考虑优化

    我开这个题的时候最先想到的是贪心算法 , 后来觉得贪心可能会处理挺多细节,就开始换成(dp)思考

    显然对贪心来说,如果i要转移的话,一定是向左右两边油价更低的地方转移,然后步步逼近(End)

    我们将这个贪心思想用到(dp)优化里面,对上面的方程来说要求(c)有序,然后我们现在还需要找与当前点最接近的(x)

    于是我们优化(dp)的目标就已经转化为了如何实现这个二维偏序。

    接下来的就很好说了吧,(cdq)维护二维偏序、(set+lower)_(boun)d维护凸包、李超线段树维护一次函数(你随便挑

    这里用的是(cdq)维护二维偏序

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define int long long
    #define INF 1ll<<30
    
    template<typename _T>
    inline void read(_T &x)
    {
    	x=0;char s=getchar();int f=1;
    	while(s<'0'||s>'9') {f=1;if(s=='-')f=-1;s=getchar();}
    	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
    	x*=f;
    }
    
    const int p=1e5+5;
    
    struct gas{
    	int c,x,id;
    	friend bool operator<(gas a,gas b)
    	{
    		return a.c < b.c;
    	}
    }pos[p];
    int f[p];
    
    inline int dis(int i,int j)
    {
    	return abs(pos[i].x - pos[j].x);
    }
    
    inline bool cmp(gas A,gas B)
    {
    	return A.x < B.x;
    }
    
    inline void cdq(int l,int r)
    {
    	if(l == r) return ;
    	int mid = l+r>>1;
    	cdq(l,mid);
    	sort(pos+l,pos+mid+1,cmp);
    	for(int i=mid+1;i<=r;i++)
    	{
    		int pl = upper_bound(pos + l ,pos+mid+1,pos[i],cmp) - pos;
    		if(pl == mid + 1)
    		{
    			pl -- ;
    			f[pos[i].id] = min(f[pos[pl].id] +  abs(pos[pl].x - pos[i].x) *pos[i].c  , f[pos[i].id]);
    		 }
    		else
    		{
    			f[pos[i].id] = min(f[pos[pl].id] +  abs(pos[pl].x - pos[i].x) *pos[i].c  , f[pos[i].id]);
    		 } 
    		if(pl != 1)pl--;
    		f[pos[i].id] = min(f[pos[pl].id] +  abs(pos[pl].x - pos[i].x) *pos[i].c  , f[pos[i].id]);
    	}
    	sort(pos+l,pos+mid+1);
    	cdq(mid+1,r);
    	return;
    }
    
    signed  main()
    {
    	int n,s,t;
    	
    	read(n);
    	read(s);
    	read(t); 
    	for(int i=1,c,x;i<=n;i++)
    	{
    		read(c);
    		read(x);
    		pos[i].c = c;
    		pos[i].x = x;
    		pos[i].id = i;
    	}
    	pos[n+1].c = 0;
    	pos[n+1].x = t;
    	pos[n+1].id = n+1;
    	memset(f,0x3f,sizeof(f));
    	f[n+1] = 0;
    	sort(pos+1,pos+2+n);
    	cdq(1,n + 1);
    	for(int i=1;i<=n + 1;i++)
    	{
    		if(pos[i].x == s)
    		{
    			cout<<f[pos[i].id];
    			return 0;
    		}
    	}
     }
    
    
    
  • 相关阅读:
    人工智能系统
    Maven tomcat插件配置和使用
    青春谁不糊涂3
    假设但是学习java入门,请离开SSH稍远
    Linux下top订购具体解释
    Unity3d + NGUI 多分辨率适应
    Delphi 注册文件类型 设置文件图标
    如何创建自定义的文件类型关联
    delphi 中字符串与16进制、10进制转换函数
    十六进制字符串转化成字符串输出HexToStr(Delphi版、C#版)
  • 原文地址:https://www.cnblogs.com/-Iris-/p/15350329.html
Copyright © 2011-2022 走看看