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
  • 相关阅读:
    Leetcode 349. Intersection of Two Arrays
    hdu 1016 Prime Ring Problem
    map 树木品种
    油田合并
    函数学习
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 101. Symmetric Tree
    poj 2524 Ubiquitous Religions(宗教信仰)
    pat 1009. 说反话 (20)
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13456403.html
Copyright © 2011-2022 走看看