• [loj3156]回家路线


    令$dp[i]$表示经过第$i$条边后的最小烦躁值,有$且dp[i]=min_{y_{j}=x_{i}且q_{j}le p_{i}}dp[j]+f(p_{i}-q_{j})$,其中$f(x)=Ax^{2}+Bx+C$
    由于$p_{j}<q_{j}le p_{i}$,按$p_{i}$从小到大枚举,当$q_{j}le p_{i}$时将信息记在$y_{j}$上,求$dp[i]$时枚举$x_{i}$上的信息即可,复杂度$o(m^{2})$
    将后面的式子拆开,提出与$j$无关的部分,即$且dp[i]=f(p_{i})+min_{y_{j}=x_{i}且q_{j}le p_{i}}-2Ap_{i}q_{j}+(dp[j]+Aq_{j}^2-Bq_{j})$
    将后半部分看作$F_{j}(x)=-2Aq_{j}x+(dp[j]+Aq_{j}^2-Bq_{j})$的直线,对每一个点用凸包来维护这些直线,利用斜率$q_{j}$和询问$p_{i}$的单调性可以做到均摊$o(1)$
    复杂度计算:每一条直线插入/询问一次,插入/删除均摊均为$o(1)$,总复杂度$o(m)$;对$p_{j}le p_{i}<q_{j}$的直线维护一个$set$,复杂度为$o(mlog m)$(对$q$排序可以做到$o(m)$,但排序复杂度也为$o(mlog m)$)
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 200005
     4 #define k(i) -2*A*e[i].q
     5 #define b(i) (dp[i]+A*e[i].q*e[i].q-B*e[i].q) 
     6 struct ji{
     7     int x,y,p,q;
     8 }e[N];
     9 vector<int>v[N];
    10 set<pair<int,int> >s;
    11 int n,m,A,B,C,ans,sz[N],dp[N];
    12 bool cmp(ji x,ji y){
    13     return x.p<y.p;
    14 }
    15 double point(int x,int y){
    16     if (k(x)==k(y)){
    17         if (b(x)==b(y))return 0;
    18         if (b(x)<b(y))return 0x3f3f3f3f;
    19         return -0x3f3f3f3f;
    20     }
    21     return 1.0*(b(y)-b(x))/(k(x)-k(y));
    22 }
    23 void add(int x){
    24     int k=e[x].y;
    25     while ((sz[k]>1)&&(point(v[k][sz[k]-2],v[k][sz[k]-1])>point(v[k][sz[k]-1],x))){
    26         v[k].erase(--v[k].end());
    27         sz[k]--;
    28     }
    29     v[k].push_back(x);
    30     sz[k]++;
    31 }
    32 int query(int x){
    33     int k=e[x].x;
    34     if (!sz[k])return 0x3f3f3f3f;
    35     while ((sz[k]>1)&&(point(v[k][0],v[k][1])<e[x].p)){
    36         v[k].erase(v[k].begin());
    37         sz[k]--;
    38     }
    39     return k(v[k][0])*e[x].p+b(v[k][0]);
    40 }
    41 int main(){
    42     freopen("route.in","r",stdin);
    43     freopen("route.out","w",stdout);
    44     scanf("%d%d%d%d%d",&n,&m,&A,&B,&C);
    45     for(int i=1;i<=m;i++)scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].p,&e[i].q);
    46     sort(e+1,e+m+1,cmp);
    47     e[0].y=1;
    48     s.insert(make_pair(0,0));
    49     for(int i=1;i<=m;i++){
    50         while ((s.size())&&((*s.begin()).first<=e[i].p)){
    51             add((*s.begin()).second);
    52             s.erase(s.begin());
    53         }
    54         dp[i]=query(i)+A*e[i].p*e[i].p+B*e[i].p+C;
    55         s.insert(make_pair(e[i].q,i));
    56     }
    57     ans=0x3f3f3f3f;
    58     for(int i=1;i<=m;i++)
    59         if (e[i].y==n)ans=min(ans,dp[i]+e[i].q);
    60     printf("%d",ans);
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    聊聊我在微软外服大数据分析部门的工作经历及一些个人见解
    WPF ScrollViewer(滚动条) 自定义样式表制作 (改良+美化)
    WPF Calendar 日历控件 样式自定义
    c# 委托 事件 lamda 简写
    WPF 启动唯一程序(项目,exe,实例)
    WPF 控件 深度克隆
    c# 枚举操作 正运算 逆运算
    WPF ScrollViewer(滚动条) 自定义样式表制作 图文并茂
    WPF查找子控件和父控件方法
    建立小型开发团队的工作协作:任务日历
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13534729.html
Copyright © 2020-2023  润新知