Submission #1193287

#TimeUsernameProblemLanguageResultExecution timeMemory
1193287vnedu물병 (JOI14_bottle)C++17
70 / 100
5093 ms85072 KiB
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

template<class T> bool maximize(T &a, const T &b){ return (a < b ? a = b, 1 : 0); }
template<class T> bool minimize(T &a, const T &b){ return (a > b ? a = b, 1 : 0); }

#define fi first
#define se second

#define pb push_back
#define ii pair<int, int>

#define all(x) x.begin(), x.end()

#define TASK "nonsense"

/// end of template ///

const int N = 2e3 + 10;
const int P = 2e5 + 10;
const int Q = 2e5 + 10;
const int M = 2e5 + 10;
const int inf = 1e9;
struct Dsu
{
    int n,par[M];
    Dsu() {}
    void init(int _n)
    {
        n=_n;
        for(int i=1;i<=n;++i) par[i]=i;
    }
    int get(int x)
    {
        if(x==par[x]) return x;
        return par[x]=get(par[x]);
    }
    bool unite(int x, int y)
    {
        int s=get(x),t=get(y);
        if(s==t) return 0;
        par[s]=t;
        return 1;
    }
} dsu;
struct Edge
{
    int u,v,w;
    Edge() {w=inf;}
    Edge(int u, int v, int w) : u(u),v(v),w(w) {}
    bool operator < (const Edge &S) const
    {
        return w<S.w;
    }
} edge[P];
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
int n,m,_p,numQuery,numEdge=0,lo[Q],hi[Q],mid[Q],ans[Q],cur[Q],ptr,root[P];
char a[N][N];
ii p[P],query[Q];
pair<ii,ii> best[N][N];
Edge cm[P];
queue<ii> q;
bool ok[Q],process[N][N];
bool cmp(int x, int y)
{
    return mid[x]<mid[y];
}
void solve()
{
    cin>>n>>m>>_p>>numQuery;
    for(int i=1;i<=n;++i)
    {
        string s; cin>>s;
        for(int j=1;j<=m;++j) a[i][j]=s[j-1];
    }
    for(int i=1;i<=_p;++i)
    {
        int x,y; cin>>x>>y;
        p[i]={x,y};
    }
    dsu.init(_p);
    while(1)
    {
        int old=0;
        for(int i=1;i<=_p;++i) old+=(dsu.get(i)==i);
        for(int i=1;i<=n;++i) for(int j=1;j<=m;++j)
            best[i][j]={make_pair(-1,inf),make_pair(-1,inf)};
        for(int i=1;i<=_p;++i)
        {
            root[i]=dsu.get(i);
            int x=p[i].fi,y=p[i].se;
            best[x][y].fi={i,0};
            q.push({x,y});
        }
//        int dpt=0;
        while(!q.empty())
        {
//            ++dpt;
//            if(dpt==100) return;
            int i=q.front().fi;
            int j=q.front().se;
            q.pop();
//            cout<<i<<' '<<j<<'\n';
            for(int k=0;k<4;++k)
            {
                int i2=i+dx[k];
                int j2=j+dy[k];
                if(i2>=1 && i2<=n && j2>=1 && j2<=m && a[i2][j2]=='.')
                {
                    ii cur;
                    pair<ii,ii> &gogo=best[i2][j2];
                    cur=best[i][j].fi;
                    bool ok=0;
                    if(cur.fi!=-1)
                    {
                        ++cur.se;
                        bool gg=0;
                        if(gogo.fi.fi!=-1 && root[gogo.fi.fi]==root[cur.fi])
                        {
                            if(minimize(gogo.fi.se,cur.se)) ok=1;
                            gg=1;
                        }
                        if(gogo.se.fi!=-1 && root[gogo.se.fi]==root[cur.fi])
                        {
                            if(minimize(gogo.se.se,cur.se)) ok=1;
                            gg=1;
                        }
                        if(gg==1)
                        {
                            if(gogo.se.se<gogo.fi.se) swap(gogo.fi,gogo.se);
                        }
                        else if(cur.se<=gogo.fi.se) gogo.se=gogo.fi,gogo.fi=cur,ok=1;
                        else if(cur.se<gogo.se.se) gogo.se=cur,ok=1;
                    }
                    cur=best[i][j].se;
                    if(cur.fi!=-1)
                    {
                        ++cur.se;
                        bool gg=0;
                        if(gogo.fi.fi!=-1 && root[gogo.fi.fi]==root[cur.fi])
                        {
                            if(minimize(gogo.fi.se,cur.se)) ok=1;
                            gg=1;
                        }
                        if(gogo.se.fi!=-1 && root[gogo.se.fi]==root[cur.fi])
                        {
                            if(minimize(gogo.se.se,cur.se)) ok=1;
                            gg=1;
                        }
                        if(gg==1)
                        {
                            if(gogo.se.se<gogo.fi.se) swap(gogo.fi,gogo.se);
                        }
                        else if(cur.se<=gogo.fi.se) gogo.se=gogo.fi,gogo.fi=cur,ok=1;
                        else if(cur.se<gogo.se.se) gogo.se=cur,ok=1;
                    }
//                    cout<<ok<<"   "<<i2<<' '<<j2<<'\n';
                    if(ok) q.push({i2,j2});
                }
            }
        }
//        return;
        for(int i=1;i<=_p;++i) cm[i]=Edge();
//        for(int i=1;i<=n;++i)
//        {
//            for(int j=1;j<=m;++j) cout<<best[i][j].se.fi<<' ';
//            cout<<'\n';
//        }
        for(int i=1;i<=_p;++i)
        {
            int x=p[i].fi,y=p[i].se;
            ii cur=best[x][y].se;
            if(cur.fi==-1) continue;
//            cout<<"DSAD";
            Edge gaugau=Edge(i,cur.fi,cur.se);
//            if(gaugau.w<cm[root[i]].w) cout<<"DASD\n";
            if(gaugau.w<=cm[root[i]].w) cm[root[i]]=gaugau;
        }
        for(int i=1;i<=_p;++i) if(root[i]==i && cm[i].w!=inf)
        {
            int doi=root[cm[i].v];
            if(dsu.get(i)!=dsu.get(doi))
            {
                edge[++numEdge]=cm[i];
                dsu.unite(i,doi);
            }
        }
        int cnt=0;
        for(int i=1;i<=_p;++i) cnt+=(dsu.get(i)==i);
//        cout<<old<<' '<<cnt<<'\n';
//        cout<<old<<'\n';
        if(old==cnt) break;
    }
//    for(int i=1;i<=numEdge;++i)
//    {
//        cout<<edge[i].u<<' '<<edge[i].v<<' '<<edge[i].w<<'\n';
//    }
//    return;
    sort(edge+1,edge+1+numEdge);
//    int sum=0;
//    for(int i=1;i<=numEdge;++i) sum+=edge[i].w;
//    cout<<sum<<'\n';
    for(int i=1;i<=numQuery;++i)
    {
        cin>>query[i].fi>>query[i].se;
        ans[i]=inf;
        lo[i]=1;
        hi[i]=numEdge;
    }
    for(int tri=1;tri<=20;++tri)
    {
        ptr=0;
        memset(ok,0,sizeof(ok));
        dsu.init(_p);
        for(int i=1;i<=numQuery;++i) if(lo[i]<=hi[i])
        {
            mid[i]=(lo[i]+hi[i])>>1;
            cur[++ptr]=i;
        }
//        break;
        sort(cur+1,cur+1+ptr,cmp);
        int num=0;
        for(int i=1;i<=ptr;++i)
        {
            int id=cur[i];
            while(num<mid[id])
            {
                ++num;
                dsu.unite(edge[num].u,edge[num].v);
            }
            ok[id]=(dsu.get(query[id].fi)==dsu.get(query[id].se));
        }
//        break;
        for(int i=1;i<=numQuery;++i) if(lo[i]<=hi[i])
        {
            if(ok[i]) ans[i]=edge[mid[i]].w,hi[i]=mid[i]-1;
            else lo[i]=mid[i]+1;
        }
    }
    for(int i=1;i<=numQuery;++i) cout<<(ans[i]==inf?-1:ans[i]-1)<<'\n';
//    for(int i=1;i<=numQuery;++i) cerr<<(ans[i]==inf?-1:ans[i]-1)<<'\n';
}
int main()  {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

//    freopen(TASK".inp","r",stdin);
//    freopen(TASK".out","w",stdout);

    int testcase=1;
//    cin>>testcase;

    while (testcase--)
        solve();

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...