zoukankan      html  css  js  c++  java
  • bzoj 4456 [Zjoi2016]旅行者

    题面

    https://www.lydsy.com/JudgeOnline/problem.php?id=4456

    题解

    分治

    设当前work的区间为(x1,y1,x2,y2)

    我们将长边分成两半

    不妨设长边是(x1,x2)

    那么令mid=(x1+x2)/2

    对于分界线(mid,y1)~(mid,y2)的所有点 我们做最短路

    得到分界线上所有点到区间里任意点的最短路

    那么对于询问(sx,sy,tx,ty) 我们可以枚举分界线上某一点(mid,y) 并且用dist((mid,y),(sx,sy))+dist((mid,y),(tx,ty))更新答案

    然后对于(sx,sy)和(tx,ty)都落在分界线同一侧的询问我们递归求解

    这样做的正确性:每一组询问,一定会经过某次的分界线,在计算到这条分界线的时候就可以算到答案

    复杂度:T(n)=4T(n/2)+O(n*(m+nlogm))  m为边数也就是n^2

    那么T(n)=n^3(这是n约等于m的情况) 可以通过这道题

    n和m差距大的时候更快

    Code

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 
      5 ll read(){
      6     ll x=0,f=1;char c=getchar();
      7     while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
      8     while(c>='0' && c<='9'){x=x*10+c-'0';c=getchar();}
      9     return x*f;
     10 }
     11 
     12 const int maxn=100100;
     13 int n,m,q;
     14 int a[150][maxn],b[150][maxn];
     15 bool vis[150][maxn];
     16 bool flag;
     17 int res[100100];
     18 
     19 struct P{
     20     int x;
     21     pair<int,int> y;
     22     bool operator <(const P &a) const{
     23         return x>a.x;
     24     }
     25 };
     26 
     27 priority_queue<P> pq;
     28 
     29 struct query{
     30     int a,b,c,d;
     31     int p,ans;
     32     void input(){
     33         a=read(),b=read(),c=read(),d=read();
     34     }
     35 } que[100100];
     36 
     37 int dis[150][maxn];
     38 int num[150][maxn];
     39 
     40 void update(int nwx,int nwy,int nwdis){
     41     //cout<<nwx<<' '<<nwy<<' '<<nwdis<<endl;
     42     if(dis[nwx][nwy]>nwdis){
     43         dis[nwx][nwy]=nwdis;
     44         pq.push(P{nwdis,make_pair(nwx,nwy)});
     45     }
     46 }
     47 void doit(int x,int y,int X1,int Y1,int X2,int Y2){
     48     //cout<<X1<<' '<<Y1<<' '<<X2<<' '<<Y2<<' '<<x<<' '<<y<<endl;
     49     for(int i=X1;i<=X2;i++)
     50         for(int j=Y1;j<=Y2;j++)
     51             dis[i][j]=1e9,vis[i][j]=0;
     52     dis[x][y]=0;
     53     pq.push(P{0,make_pair(x,y)});
     54     while(!pq.empty()){
     55         P nw=pq.top();
     56         pq.pop();
     57         int X=nw.y.first,Y=nw.y.second;
     58         //cout<<X<<' '<<Y<<' '<<dis[X][Y]<<endl;
     59         if(vis[X][Y]) continue;
     60         vis[X][Y]=1;int dist=dis[X][Y];
     61         if(X>X1) update(X-1,Y,dist+b[X-1][Y]);
     62         if(X<X2) update(X+1,Y,dist+b[X][Y]);
     63         if(Y>Y1) update(X,Y-1,dist+a[X][Y-1]);
     64         if(Y<Y2) update(X,Y+1,dist+a[X][Y]);
     65     }
     66 }
     67 
     68 void solve(int nwa,int nwb,int nwc,int nwd,int l,int r){
     69     //cout<<nwa<<' '<<nwb<<' '<<nwc<<' '<<nwd<<endl;
     70     if(l>r) return;
     71     int len1=nwc-nwa+1,len2=nwd-nwb+1;
     72     if(len1>=len2){
     73         int md=(nwa+nwc)>>1;
     74         for(int j=nwb;j<=nwd;j++){
     75             doit(md,j,nwa,nwb,nwc,nwd);
     76             for(int k=l;k<=r;k++){
     77                 //cout<<que[k].p<<' '<<dis[que[k].a][que[k].b]<<' '<<dis[que[k].c][que[k].d]<<endl;
     78                 que[k].ans=min(que[k].ans,dis[que[k].a][que[k].b]+dis[que[k].c][que[k].d]);
     79             }
     80         }
     81         if(nwa<md){
     82             int pos=l-1;
     83             for(int i=l;i<=r;i++){
     84                 if(que[i].a<md && que[i].c<md) pos++,swap(que[i],que[pos]);
     85             }
     86             solve(nwa,nwb,md-1,nwd,l,pos);
     87         }
     88         if(md<nwc){
     89             int pos=l-1;
     90             for(int i=l;i<=r;i++){
     91                 if(que[i].a>md && que[i].c>md) pos++,swap(que[i],que[pos]);
     92             }
     93             solve(md+1,nwb,nwc,nwd,l,pos);
     94         }
     95     }
     96     else{
     97         int md=(nwb+nwd)>>1;
     98         for(int i=nwa;i<=nwc;i++){
     99             doit(i,md,nwa,nwb,nwc,nwd);
    100             for(int k=l;k<=r;k++){
    101                 //cout<<que[k].p<<' '<<dis[que[k].a][que[k].b]<<' '<<dis[que[k].c][que[k].d]<<endl;                
    102                 que[k].ans=min(que[k].ans,dis[que[k].a][que[k].b]+dis[que[k].c][que[k].d]);
    103             }
    104         }
    105         if(nwb<md){
    106             int pos=l-1;
    107             for(int i=l;i<=r;i++){
    108                 if(que[i].b<md && que[i].d<md) pos++,swap(que[i],que[pos]);
    109             }
    110             solve(nwa,nwb,nwc,md-1,l,pos);
    111         }
    112         if(md<nwd){
    113             int pos=l-1;
    114             for(int i=l;i<=r;i++){
    115                 if(que[i].b>md && que[i].d>md) pos++,swap(que[i],que[pos]);
    116             }
    117             solve(nwa,md+1,nwc,nwd,l,pos);
    118         }
    119     }
    120 }
    121 
    122 int main(){
    123 #ifdef LZT
    124     freopen("in","r",stdin);
    125     freopen("out","w",stdout);
    126 #endif
    127     n=read();m=read();
    128     if(n>m) flag=1;
    129     for(int i=1;i<=n;i++){
    130         for(int j=1;j<m;j++){
    131             if(!flag) a[i][j]=read();
    132             else b[j][i]=read();
    133         }
    134     }
    135     for(int i=1;i<n;i++){
    136         for(int j=1;j<=m;j++){
    137             if(!flag) b[i][j]=read();
    138             else a[j][i]=read();
    139         }
    140     }
    141     q=read();
    142     for(int i=1;i<=q;i++){
    143         que[i].input();
    144         if(flag) swap(que[i].a,que[i].b),swap(que[i].c,que[i].d);
    145         que[i].p=i;que[i].ans=2e9;
    146     }
    147     if(flag) swap(n,m);
    148     
    149     solve(1,1,n,m,1,q);
    150 
    151     for(int i=1;i<=q;i++)
    152         res[que[i].p]=que[i].ans;
    153     for(int i=1;i<=q;i++)
    154         printf("%d
    ",res[i]);
    155     return 0;
    156 }
    157 
    158 /*
    159 2 2
    160 2
    161 3
    162 6 4
    163 2
    164 1 1 2 2
    165 1 2 2 1
    166 */
    View Code

    Review

    分治还是比较明显的

    然而数据的处理十分麻烦

    因为条件是n×m的范围

    所以我们得同时考虑n=m和n>>m的情况

    代码中的处理方法是跟别人学的 很棒棒 要多写几遍

  • 相关阅读:
    sql查询指定表外键约束
    C#6.0新特性
    事务嵌套
    怎么在项目中应用委托
    单线程与多线程
    winform线程下载网页信息
    Linux笔记 FHS目录结构
    Linux笔记 Linux文件系统
    Linux笔记 软件管理
    Linux笔记 vi/vim编辑器
  • 原文地址:https://www.cnblogs.com/wawawa8/p/9387861.html
Copyright © 2011-2022 走看看