• [NOI2019] 回家路线


    link

    $solution:$

    算法一

    通过观察范围发现 $qleq1000$ ,所以直接暴力拆点 $dp$ 。时间复杂度 $O(1000m)=O(能过)$ 。

    算法二

    因为有 $A imes x^2+B imes x+C$ 考虑斜率优化。

    设 $f_i$ 表示走完第 $i$ 条边的最小烦躁值,则 $f_i=min{f_j+A imes (p_i-q_j)^2+B imes (p_i-q_j)+C}space (u_i=v_j,p_igeq q_j)$ 。

    可以发现现在的瓶颈是如何快速处理 $u_i=v_j,p_igeq q_j$。

    通过算法一可以得到通过将 $p$ 排序处理顺序,然后就将决策边放入其 $v_j$ 中 。

    每次取出 $q$ 值,插入相对应的 $v$ 中既可以找到决策点。

    然后就斜率优化即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<climits>
    using namespace std;
    inline int read(){
        int f=1,ans=0;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
        return f*ans;
    }
    const int MAXN=200001;
    deque<int> que[MAXN];
    int n,m,A,B,C,f[MAXN];
    struct node{
        int u,v,p,q;
    }g[MAXN];
    vector<int> ve[MAXN];
    vector<int> pre[MAXN];
    int X(int id){return g[id].q;}
    int Y(int id){return f[id]+A*g[id].q*g[id].q-B*g[id].q;}
    void insert(int id){
        int ps=g[id].v;
        while(que[ps].size()>=2){
            int las2=que[ps].back();que[ps].pop_back();
            int las1=que[ps].back();que[ps].pop_back();
            if((Y(las2)-Y(las1))*(X(id)-X(las1))<(Y(id)-Y(las1))*(X(las2)-X(las1))){
                que[ps].push_back(las1);
                que[ps].push_back(las2);
                break;
            }
            que[ps].push_back(las1);
        }que[ps].push_back(id);
    //    printf("id:%d ps:%d front:%d
    ",id,ps,que[ps].front());
    }
    void del(int id){
        int ps=g[id].u;
        while(que[ps].size()>=2){
            int las1=que[ps].front();que[ps].pop_front();
            int las2=que[ps].front();que[ps].pop_front();
            if((Y(las2)-Y(las1))>((X(las2)-X(las1))*2*A*g[id].p)){
                que[ps].push_front(las2);
                que[ps].push_front(las1);
                break;
            }que[ps].push_front(las2);
        }return;
    }
    int Minn=INT_MAX;
    int calc(int G){return A*G*G+B*G+C;}
    int main(){
        freopen("route.in","r",stdin);
        freopen("route.out","w",stdout);
    //    freopen("1.in","r",stdin);
        n=read(),m=read(),A=read(),B=read(),C=read();
        for(int i=1;i<=m;i++) g[i].u=read(),g[i].v=read(),g[i].p=read(),g[i].q=read(),ve[g[i].p].push_back(i);
        memset(f,127/3,sizeof(f));
        que[1].push_back(0);f[0]=0;
        for(int i=1;i<=1000;i++){
            int Siz=pre[i].size();
            for(int j=0;j<Siz;j++) insert(pre[i][j]);
            Siz=ve[i].size();
            for(int j=0;j<Siz;j++){
                int id=ve[i][j],ps=g[id].u;
    //            if(i==9){printf("size:%d
    ",que[2].size());}
                del(id);
                if(que[ps].empty()) continue;
                f[id]=f[que[ps].front()]+calc(g[id].p-g[que[ps].front()].q);
                pre[g[id].q].push_back(id);
            }
        }
    //    for(int i=1;i<=m;i++) printf("X(%d):%d Y(%d):%d
    ",i,X(i),i,Y(i));
    //    for(int i=1;i<=m;i++) printf("f(%d):%d
    ",i,f[i]);
        for(int i=1;i<=m;i++) if(g[i].v==n) Minn=min(Minn,f[i]+g[i].q);
        printf("%d
    ",Minn);return 0;
    }
    View Code
  • 相关阅读:
    关于在pycharm下提示ModuleNotFoundError: No module named 'XXX' 的一种可能
    记录Python类与继承的一个错误
    JavaScript 中this 初步理解笔记
    Kibana6.x.x源码分析--如何自定义savedObjectType对象
    Kibana6.x.x源码分析--如何使用kibana的savedObjectType对象
    AngularJs依赖注入写法笔记
    Kibana6.x.x源码分析--ngReact使用
    Kibana6.x.x源码分析--Error: $injector:nomod Module Unavailable
    互联网时代,我们可以选择不做穷人
    ES6问题记录--Promise
  • 原文地址:https://www.cnblogs.com/si-rui-yang/p/11217258.html
Copyright © 2020-2023  润新知