[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(m\log m)$(对$q$排序可以做到$o(m)$,但排序复杂度也为$o(m\log 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

 

posted @ 2020-08-20 14:08  PYWBKTDA  阅读(135)  评论(0编辑  收藏  举报