zoukankan      html  css  js  c++  java
  • P7480 Reboot from Blue

    P7480 Reboot from Blue(最短路,李超树优化dp)

    首先,我们发现,直接建图跑最短路肯定不行,因为这样做会有 (O(n^2)) 条边。

    那么我们可以考虑减少无用的边。

    有这样一个性质:对于一个点,我们发现它只会取到离它左最近或者右最近的比当前点油费小的点。

    这是为什么呢?因为相当于如果我们走到这个左端点或者右端点的时候,我们无论是向左还是向右,我们都有更好的选择:在那一个油站加油,再去往下一个目的地。

    同样的,为什么是比当前点油价小呢,显而易见,这是因为如果某个地方比当前点油价还要高,那我们还不如就用当前点的油了。

    也就是说,这样的话我们只需要把每一个点对于左边和右边各一个点连边即可,这样边数的级别就变成 (O(n)) 了。

    最后我们再给终点新建一个对应的结点,跑一遍从 (s) 对应点到 (t) 对应点的最短路即可。

    时间复杂度 (O(nlogn))

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    #define ll long long
    const int N=2e6+5;
    const ll INF=2e18+5;
    int n,hh=1,tt=0,sta[N],dp[N];
    struct node{
    	ll val;int pos,id;
    }a[N];
    inline bool cmp(node x,node y){return x.pos<y.pos;}
    int head[N],nex[N<<1],to[N<<1],idx,s,t;
    ll val[N<<1],dis[N];
    bool vis[N];
    void add(int u,int v,ll w){
    	nex[++idx]=head[u];
    	to[idx]=v;
    	head[u]=idx;
    	val[idx]=w;
    	return ;
    }
    #define PII pair<ll,int>
    priority_queue<PII,vector<PII>,greater<PII> >q; 
    void dijkstra(){
    	for(int i=1;i<=n;i++) dis[i]=INF;
    	dis[s]=0;
    	q.push(make_pair(0,s));
    	while(!q.empty()){
    		PII t=q.top();q.pop();
    		int x=t.second;ll dist=t.first;
    		if(vis[x]) continue;
    		vis[x]=true;
    		for(int i=head[x];i;i=nex[i]){
    			int y=to[i];
    			if(dist+val[i]<dis[y]){
    				dis[y]=dist+val[i];
    				q.push(make_pair(dis[y],y)); 
    			}
    		}
    	}
    	return ;
    }
    signed main(){
        read(n),read(s),read(t);
        for(int i=1;i<=n;i++) read(a[i].val),read(a[i].pos),a[i].id=i;
        sort(a+1,a+n+1,cmp);
        for(int i=n;i>=1;i--){
            while(hh<=tt&&a[i].val<=a[sta[tt]].val) --tt;
            dp[i]=sta[tt];
            sta[++tt]=i;
        }
        for(int i=1;i<=n;i++) if(dp[i]) add(i,dp[i],abs(a[i].pos-a[dp[i]].pos)*a[i].val);
        tt=0,hh=1;
        for(int i=1;i<=n;i++){
            while(hh<=tt&&a[i].val<=a[sta[tt]].val) --tt;
            dp[i]=sta[tt];
            sta[++tt]=i;
        }
        for(int i=1;i<=n;i++) if(dp[i]) add(i,dp[i],abs(a[i].pos-a[dp[i]].pos)*a[i].val);
        for(int i=1;i<=n;i++) if(a[i].pos==s){s=i;break;}
        n++;
        for(int i=1;i<n;i++) add(i,n,abs(t-a[i].pos)*a[i].val);
        dijkstra();
        write(dis[n]);
        return 0;
    }
    
  • 相关阅读:
    Spring使用Jackson处理json数据
    手工搭建web项目
    购物车模块
    C# ——利用反射动态加载dll
    C# —— 利用Marshal.GetDelegateForFunctionPointer 来转换一个函数指针为一个委托
    C# —— GetProcAddress函数检索指定的动态链接库(DLL)中的输出库函数地址。
    c#——IntPtr
    C#-StructLayoutAttribute(结构体布局)
    C#报错——传递数组对象报错“未将对象引用设置到对象的实例”
    C#——保留小数点,强转
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14667444.html
Copyright © 2011-2022 走看看