zoukankan      html  css  js  c++  java
  • [loj3180]天桥

    考虑将所有交点作为关键点来建图跑最短路,但图上的关键点数量最坏为$o(nm)$,需要优化
    当$s=0$且$g=n-1$的部分分,有以下结论:
    1.对于一段天桥$([l,r],y)$,不会从$(r,y)$向左移动到$(l,y)$,否则必然曾经过$(l,y')$,不如$(l,y')=>(l,y)$更优
    2.对于一座天桥$([l,r],y)$,不会从竖直方向经过$(l',y)$,否则必然曾经过$(l,y')$,不如$(l,y')=>(l,y)=>(l',y)$更优
    3.对于一座天桥$([l,r],y)$,不会从$(x,y)$向下移动,否则必然会再经过$(x',y)$或$(r,y')$,前者根据结论2一定不优,后者不如$(x,y)=>(r,y)=>(r,y')$更优
    对于一座天桥$([l,r],y)$,其中$(x,y)$为关键点当且仅当$x=l$或$x=r$或其向上走经过的第一个交点为天桥端点,那么点数最多为$3m$,即解决了$s=0$且$t=n-1$的部分分
    那么对于原题,先不妨假设$s<g$,那么对于一座天桥$([l,r],y)$,其要特殊考虑当且仅当$l<s$或$g<r$,以$l<s$为例:找到$s$左边/右边(包括$s$)第一个能上桥的点$a$和$b$($h_{a,b}ge y$),那么将整座桥拆成$([l,a],y)$,$([a,b],y)$和$([b,r],y)$即可
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 100005
      4 #define oo 1e15
      5 #define L (k<<1)
      6 #define R (L+1)
      7 #define mid (l+r>>1)
      8 #define pii pair<int,int>
      9 #define mp make_pair
     10 #define fi first
     11 #define se second
     12 struct ji{
     13     int nex,to,len;
     14 }edge[N*80];
     15 struct build{
     16     int x,h;
     17 }bu[N];
     18 struct bridge{
     19     int l,r,y;
     20     bool operator < (const bridge &k)const{
     21         return (y<k.y)||(y==k.y)&&(l<k.l);
     22     }
     23 }br[N*5];
     24 priority_queue<pair<long long,int> >q;
     25 map<pii,int>mat;
     26 vector<pii>v;
     27 int V,E,n,m,s,t,f[N<<2],head[N*20],vis[N*20];
     28 long long ans,d[N*20];
     29 bool cmp(pii x,pii y){
     30     return (x.se<y.se)||(x.se==y.se)&&(x.fi<y.fi);
     31 }
     32 void build(int k,int l,int r){
     33     if (l==r){
     34         f[k]=bu[l].h;
     35         return;
     36     }
     37     build(L,l,mid);
     38     build(R,mid+1,r);
     39     f[k]=max(f[L],f[R]);
     40 }
     41 int find1(int k,int l,int r,int x,int y,int z){
     42     if ((l>y)||(x>r)||(f[k]<z))return 0;
     43     if (l==r)return l;
     44     int a=find1(R,mid+1,r,x,y,z);
     45     if (a)return a;
     46     return find1(L,l,mid,x,y,z);
     47 }
     48 int find2(int k,int l,int r,int x,int y,int z){
     49     if ((l>y)||(x>r)||(f[k]<z))return 0;
     50     if (l==r)return l;
     51     int a=find2(L,l,mid,x,y,z);
     52     if (a)return a;
     53     return find2(R,mid+1,r,x,y,z);
     54 }
     55 void update(int k,int l,int r,int x,int y,int z){
     56     if ((l>y)||(x>r))return;
     57     if ((x<=l)&&(r<=y)){
     58         f[k]=max(f[k],z);
     59         return;
     60     }
     61     update(L,l,mid,x,y,z);
     62     update(R,mid+1,r,x,y,z);
     63 }
     64 int query(int k,int l,int r,int x){
     65     if (l==r)return f[k];
     66     if (x<=mid)return max(f[k],query(L,l,mid,x));
     67     return max(f[k],query(R,mid+1,r,x));
     68 }
     69 void add(int x,int y,int z){
     70     edge[E].nex=head[x];
     71     edge[E].to=y;
     72     edge[E].len=z;
     73     head[x]=E++;
     74 }
     75 void split(int k,int x){
     76     if ((x)&&(br[k].l<x)&&(x<br[k].r)){
     77         br[++m]=bridge{br[k].l,x,br[k].y};
     78         br[k].l=x;
     79     }
     80 }
     81 void split(){
     82     build(1,1,n);
     83     for(int i=1;i<=m;i++){
     84         int a,b;
     85         if (br[i].l<s){
     86             split(i,find1(1,1,n,1,s,br[i].y));
     87             split(i,find2(1,1,n,s,n,br[i].y));
     88         }
     89         if (t<br[i].r){
     90             split(i,find1(1,1,n,1,t,br[i].y));
     91             split(i,find2(1,1,n,t,n,br[i].y));
     92         }
     93     }
     94 }
     95 void build(){
     96     memset(head,-1,sizeof(head));
     97     sort(v.begin(),v.end());
     98     for(int i=0;i<v.size();i++)
     99         if ((!i)||(v[i-1]!=v[i]))mat[v[i]]=++V;
    100     for(int i=0,j=0;i<v.size();i=++j)
    101         for(;((j<v.size())&&(v[j].fi==v[j+1].fi));j++)
    102             if (v[j].se!=v[j+1].se){
    103                 add(mat[v[j]],mat[v[j+1]],v[j+1].se-v[j].se);
    104                 add(mat[v[j+1]],mat[v[j]],v[j+1].se-v[j].se);
    105             }
    106     sort(v.begin(),v.end(),cmp);
    107     for(int i=1,j=0;i<=m;i++){
    108         while ((br[i].y!=v[j].se)||(br[i].l!=v[j].fi))j++;
    109         for(;((br[i].y!=v[j].se)||(br[i].r!=v[j].fi));j++)
    110             if (v[j].fi!=v[j+1].fi){
    111                 add(mat[v[j]],mat[v[j+1]],bu[v[j+1].fi].x-bu[v[j].fi].x);
    112                 add(mat[v[j+1]],mat[v[j]],bu[v[j+1].fi].x-bu[v[j].fi].x);
    113             }
    114     }
    115 }
    116 long long dij(int s,int t){
    117     memset(vis,0,sizeof(vis));
    118     for(int i=1;i<=V;i++)d[i]=oo;
    119     d[s]=0;
    120     q.push(mp(0,s));
    121     while (!q.empty()){
    122         int k=q.top().se;
    123         q.pop();
    124         if (vis[k])continue;
    125         vis[k]=1;
    126         for(int i=head[k];i!=-1;i=edge[i].nex)
    127             if (d[edge[i].to]>d[k]+edge[i].len){
    128                 d[edge[i].to]=d[k]+edge[i].len;
    129                 q.push(mp(-d[edge[i].to],edge[i].to));
    130             }
    131     }
    132     return d[t];
    133 }
    134 int main(){
    135     scanf("%d%d",&n,&m);
    136     for(int i=1;i<=n;i++)scanf("%d%d",&bu[i].x,&bu[i].h);
    137     for(int i=1;i<=m;i++){
    138         scanf("%d%d%d",&br[i].l,&br[i].r,&br[i].y);
    139         br[i].l++,br[i].r++;
    140     }
    141     scanf("%d%d",&s,&t);
    142     s++,t++;
    143     if (s>t)swap(s,t);
    144     v.push_back(mp(s,0));
    145     v.push_back(mp(t,0));
    146     split();
    147     sort(br+1,br+m+1);
    148     memset(f,0,sizeof(f));
    149     for(int i=1,j=1;i<=m;i++){
    150         if (br[j].y<br[i].y)
    151             for(;j<i;j++)update(1,1,n,br[j].l,br[j].r,br[j].y);
    152         v.push_back(mp(br[i].l,br[i].y));
    153         v.push_back(mp(br[i].r,br[i].y));
    154         v.push_back(mp(br[i].l,query(1,1,n,br[i].l)));
    155         v.push_back(mp(br[i].r,query(1,1,n,br[i].r)));
    156     }
    157     build();
    158     ans=dij(mat[mp(s,0)],mat[mp(t,0)]);
    159     if (ans==oo)ans=-1;
    160     printf("%lld",ans);
    161 }
    View Code
  • 相关阅读:
    ApacheServer-----关于443端口被占用的解决方法
    《小强与小明》——正在疯传的伟大的故事
    不争万年,只珍朝夕------我的态度
    dubbo搭建
    使用netty的第一个Hello World
    myBatis数据库常用标签
    mysql 索引
    tomcat部署项目的一点心得
    【康托展开】
    初探计算机硬盘
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13456403.html
Copyright © 2011-2022 走看看