#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |