zoukankan      html  css  js  c++  java
  • [NOI2019] 回家路线

    题意:

    给定一张n个点m条边的有向图,每条边代表一趟车,有发车时间$p_i$和到站时间$q_i$。

    现在你要从点1坐车到点n,对于一次在点u的换乘,若你在时刻q到达u,在时刻p离开u,则会产生$A(p-q)^{2}+B(p-q)+C$的不满意度。

    若你最后在时刻p到达点n还会产生p的不满意度,求从1到n最小的不满意度。

    $nleq 10^{5},mleq 2 imes 10^{5},0leq p_i < q_i leq 10^{3}$。

    题解:

    挺水的一道题,听说场上写个$O(mt)$的分层图最短路就能过?给爷整笑了

    显然可以设$dp(i,j)$表示第i个时刻在第j个点的最小不满意度,转移类似于spfa,复杂度$O(m^{2}t)$。

    仔细考虑一下发现只有$i=q_k$的状态有用,所以总状态数是$O(m)$的,复杂度$O(m^{2})$。

    再考虑一下,这个转移显然是个斜率优化的形式,我们只需要对每个点动态建凸包即可做到$O(mlog{m})$。

    显然不能按拓扑序转移(时间混乱),考虑直接按时间转移。

    注意到每个状态的dp值都是在一条边上算出来的,于是原图就可以丢掉了。

    把每条边挂到$p_i$和$q_i$上,每个dp值在p处算出来,在q处插入凸包。

    复杂度$O(mlog{m})$。过掉这题总共花了大概2h,我没希望了

    套路:

    • 搭车问题:以时间为第一关键字转移。

    代码:

    #include<bits/stdc++.h>
    #define maxn 200005
    #define maxm 500005
    #define inf 0x7fffffff
    #define ll long long
    #define rint register ll
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define dgx cerr<<"=============="<<endl
    
    using namespace std;
    ll n,m,A,B,C;
    struct node{ll x,y;};
    struct edge{ll u,v,p,q,dp;}E[maxm];
    vector<ll> vec[maxn];
    vector<node> st[maxn];
    
    inline ll read(){
        ll x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    
    inline void ins(ll u,node c){
        while(st[u].size()>1){
            ll t=st[u].size()-1; node a=st[u][t-1],b=st[u][t];
            if((b.y-a.y)*(c.x-b.x)>=(c.y-b.y)*(b.x-a.x)) st[u].pop_back();
            else break;
        }
        st[u].push_back(c);
    }
    inline node qry(ll u,ll k){
        if(!st[u].size()) return (node){-1,-1};
        ll l=1,r=st[u].size()-1,res=0;
        while(l<=r){
            ll mid=l+r>>1;
            node a=st[u][mid-1],b=st[u][mid];
            if(b.y-a.y<=(b.x-a.x)*k) res=mid,l=mid+1;
            else r=mid-1;
        }
        return st[u][res];
    }
    inline ll getdp(node a){return a.y-A*a.x*a.x+B*a.x;}
    
    int main(){
        n=read(),m=read(),A=read(),B=read(),C=read();
        for(ll i=1;i<=m;i++){
            E[i].u=read(),E[i].v=read(),E[i].p=read(),E[i].q=read(),E[i].dp=1ll<<62;
            vec[E[i].p].push_back(i),vec[E[i].q].push_back(i);
        }
        ins(1,(node){0,0}); ll ans=1ll<<62;
        for(ll tim=0;tim<=1000;tim++){
            if(!vec[tim].size()) continue;
            for(ll i=0;i<vec[tim].size();i++){
                edge e=E[vec[tim][i]];
                if(e.q==tim && e.dp!=(1ll<<62)) 
                    ins(e.v,(node){e.q,e.dp+A*e.q*e.q-B*e.q}); 
            }
            for(ll i=0;i<vec[tim].size();i++){
                edge e=E[vec[tim][i]];
                if(e.p==tim){
                    node a=qry(e.u,2ll*A*e.p); 
                    if(a.x==-1) continue; ll x=e.p-a.x;
                    E[vec[tim][i]].dp=getdp(a)+A*x*x+B*x+C;
                    if(e.v==n) ans=min(ans,E[vec[tim][i]].dp+e.q);
                }
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    回家路线
  • 相关阅读:
    P4146 序列终结者(Splay树)
    P2617 Dynamic Rankings(树套树)
    P4168 [Violet]蒲公英(分块魔术)
    P3649[APIO2014]回文串(回文自动机)
    [IOI2011]Race(树上启发式合并)
    CentOS 7安装 .net core 环境 官网说明地址
    宝塔 Linux 面板php.ini文件在哪个目录
    KPPW部署一直提示No input file specified的Apache伪静态设置
    【分享】 MPSoC的VCU超频
    Versal AIE 上手尝鲜 2 -- Linux例程
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13336055.html
Copyright © 2011-2022 走看看