zoukankan      html  css  js  c++  java
  • 四校联考 推冰块

    image

    2<=n,m<=10^9,0<=k<=50000。

    我们发现有用的格子不是很多,经过详细的分类讨论,只有这些格子是有用的:

    imageimage

    四个角,以及障碍物(或减速带)本身和上下左右四个方向,以及障碍物所在行列(及±1的)的头尾两个。

    那么我们只要把所有 障碍 和 减速带 按x-y和y-x排序一下,对于每一个有用的格子二分一下找到往左和往右会推到哪里,连边完暴力bfs即可。

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #include <time.h>
    #include <stdlib.h>
    #include <string>
    #include <bitset>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <algorithm>
    #include <sstream>
    #include <stack>
    #include <iomanip>
    using namespace std;
    #define pb push_back
    #define mp make_pair
    typedef pair<int,int> pii;
    typedef long long ll;
    typedef double ld;
    typedef vector<int> vi;
    #define fi first
    #define se second
    #define fe first
    #define FO(x) {freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);}
    #define Edg int M=0,fst[SZ],vb[SZ],nxt[SZ];void ad_de(int a,int b){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;}void adde(int a,int b){ad_de(a,b);ad_de(b,a);}
    #define Edgc int M=0,fst[SZ],vb[SZ],nxt[SZ],vc[SZ];void ad_de(int a,int b,int c){++M;nxt[M]=fst[a];fst[a]=M;vb[M]=b;vc[M]=c;}void adde(int a,int b,int c){ad_de(a,b,c);ad_de(b,a,c);}
    #define es(x,e) (int e=fst[x];e;e=nxt[e])
    #define VIZ {printf("digraph G{
    "); for(int i=1;i<=n;i++) for es(i,e) printf("%d->%d;
    ",i,vb[e]); puts("}");}
    #ifdef LOCAL
    #define TIMER cerr<<clock()<<"ms
    "
    #else
    #define TIMER
    #endif
    #define SZ 1234567
    int n,m,k,N=0;
    int xs[SZ],ys[SZ],ts[SZ];
    typedef pair<int,int> pii;
    map<pii,int> sta;
    bool cmp2(pii a,pii b)
    {
        if(a.se!=b.se) return a.se<b.se;
        return a.fi<b.fi;
    }
    pii ps[SZ]; int pn=0;
    pii ss[SZ],rs[SZ];
    int dx[4]={1,-1,0,0},dy[4]={0,0,-1,1};
    void rec(int a,int b)
    {
        if(sta[pii(a,b)]==1) return;
        if(a<1||b<1||a>n||b>m) return;
        ps[++pn]=pii(a,b);
    }
    int ls(pii a) {return lower_bound(ps+1,ps+1+pn,a)-ps;}
    int S,T;
    int qs[SZ];
    int dist[SZ];
    #undef SZ
    #define SZ 1234567
    Edg
    void conn(pii a,pii b)
    {
        if(a==b) return;
        ad_de(ls(a),ls(b));
    }
    void spfa()
    {
        int h=0,t=0;
        qs[t++]=S; dist[S]=1;
        while(h^t)
        {
            int x=qs[h++];
            for es(x,e)
            {
                int b=vb[e];
                if(dist[b]) continue;
                dist[b]=dist[x]+1;
                qs[t++]=b;
            }
        }
    }
    int main()
    {
        FO(ice)
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%d",xs+i,ys+i,ts+i);
            sta[pii(xs[i],ys[i])]=ts[i]+1;
        }
        rec(1,1); rec(n,m);
        rec(1,m); rec(n,1);
        for(int i=1;i<=k;i++)
        {
            rec(xs[i],1); rec(xs[i],m);
            rec(1,ys[i]); rec(n,ys[i]);
            rec(xs[i]+1,1); rec(xs[i]+1,m);
            rec(xs[i]-1,1); rec(xs[i]-1,m);
            rec(1,ys[i]+1); rec(n,ys[i]+1);
            rec(1,ys[i]-1); rec(n,ys[i]-1);
            rec(xs[i],ys[i]);
            for(int j=0;j<4;j++)
            rec(xs[i]+dx[j],ys[i]+dy[j]);
        }
        sort(ps+1,ps+1+pn);
        pn=unique(ps+1,ps+1+pn)-ps-1;
        int sn=0,rn=0;
        for(int i=1;i<=k;i++)
        {
            if(ts[i]==0) ss[++sn]=pii(xs[i],ys[i]);
            else rs[++rn]=pii(xs[i],ys[i]);
        }
        ss[++sn]=pii(-2000000000,-2000000000);
        ss[++sn]=pii(2000000000,2000000000);
        rs[++rn]=pii(-2000000000,-2000000000);
        rs[++rn]=pii(2000000000,2000000000);
        sort(ss+1,ss+1+sn); sort(rs+1,rs+1+rn);
        //先处理左右 
        for(int i=1;i<=pn;i++)
        {
            int x=ps[i].fi,y=ps[i].se;
            pii cur=pii(x,y);
            if(y!=1) //L
            {
            int maxn=1;
            int id=lower_bound(rs+1,rs+1+rn,cur)-rs-1;
            pii ns=rs[id];
            if(ns.fi==x) maxn=max(maxn,ns.se);
            id=lower_bound(ss+1,ss+1+sn,cur)-ss-1;
            ns=ss[id];
            if(ns.fi==x) maxn=max(maxn,ns.se+1);
            conn(cur,pii(x,maxn));
            }
            if(y!=m) //R
            {
            int minn=m;
            int id=upper_bound(rs+1,rs+1+rn,cur)-rs;
            pii ns=rs[id];
            if(ns.fi==x) minn=min(minn,ns.se);
            id=upper_bound(ss+1,ss+1+sn,cur)-ss;
            ns=ss[id];
            if(ns.fi==x) minn=min(minn,ns.se-1);
            conn(cur,pii(x,minn));
            }
        }
        sort(ss+1,ss+1+sn,cmp2); sort(rs+1,rs+1+rn,cmp2);
        for(int i=1;i<=pn;i++)
        {
            int x=ps[i].fi,y=ps[i].se;
            pii cur=pii(x,y);
            if(x!=1) //U
            {
            int maxn=1;
            int id=lower_bound(rs+1,rs+1+rn,cur,cmp2)-rs-1;
            pii ns=rs[id];
            if(ns.se==y) maxn=max(maxn,ns.fi);
            id=lower_bound(ss+1,ss+1+sn,cur,cmp2)-ss-1;
            ns=ss[id];
            if(ns.se==y) maxn=max(maxn,ns.fi+1);
            conn(cur,pii(maxn,y));
            }
            if(x!=n) //R
            {
            int minn=n;
            int id=upper_bound(rs+1,rs+1+rn,cur,cmp2)-rs;
            pii ns=rs[id];
            if(ns.se==y) minn=min(minn,ns.fi);
            id=upper_bound(ss+1,ss+1+sn,cur,cmp2)-ss;
            ns=ss[id];
            if(ns.se==y) minn=min(minn,ns.fi-1);
            conn(cur,pii(minn,y));
            }
        }
        S=ls(pii(1,1));T=ls(pii(n,m));
        spfa(); cout<<dist[T]-1<<"
    ";
    }
  • 相关阅读:
    个人任务
    个人任务。。
    个人任务。
    个人任务
    未来周计划(一)
    澡堂人数实时查询助手的NABC分析
    react 中的fragments
    数组
    如何区分对象、数组、null
    数组的并集,交集,差集的实现
  • 原文地址:https://www.cnblogs.com/zzqsblog/p/5861998.html
Copyright © 2011-2022 走看看