社区讨论

TLE 40pts 求调

P3684[CERC2016] 机棚障碍 Hangar Hurdles参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mjwkoe97
此快照首次捕获于
2026/01/02 15:48
2 个月前
此快照最后确认于
2026/01/05 12:40
上个月
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int f=1,x=0;
	char s=getchar();
	while(s<'0'||s>'9'){
		if(s=='-') f=-1;
		s=getchar();
	}
	while(s>='0'&&s<='9'){
		x=(x<<1)+(x<<3)+(s^48);
		s=getchar();
	}
	return x*f;
}
const int N=1005,K=1e6+5;
int n;
char ch[N][N];
int sum[N][N];
bool Check(int x,int y,int k){
	if(k>=x||k>=y||x+k>n||y+k>n) return 0;
	if(sum[x+k][y+k]-sum[x-k-1][y+k]-sum[x+k][y-k-1]+sum[x-k-1][y-k-1]>=1) return 0;
	return 1;
}
int dx[4]={0,0,-1,1},dy[4]={-1,1};
int dis[N][N];
int tote;
struct Edge{
	int u,v,w;
}e[K*4];
int Id(int x,int y){
	return (x-1)*n+y;
}
int fa[K];
bool Cmp(Edge x,Edge y){
	return x.w>y.w;
}
int Find(int x){
	if(x==fa[x]) return x;
	return Find(fa[x]);
}
struct Node{
	int v,w;
};
vector<Node>mp[K];
void Kruskal(){
	for(int i=1;i<=n*n;i++) fa[i]=i;
	sort(e+1,e+tote+1,Cmp);
	for(int i=1;i<=tote;i++){
		int u=Find(e[i].u),v=Find(e[i].v);
		if(u==v) continue;
		mp[u].push_back({v,e[i].w});
		mp[v].push_back({u,e[i].w});
		fa[u]=v;
	}
}
int Idx(int x){
	return (x-1)/n+1;
}
int Idy(int x){
	if(x%n==0) return n;
	return x%n;
}
int dep[K];
int st[K][21],val[K][21];
void Dfs(int u,int f){
	dep[u]=dep[f]+1;
	st[u][0]=f;
	val[u][0]=min(dis[Idx(u)][Idy(u)],dis[Idx(f)][Idy(f)]);
	for(int i=1;i<=20;i++){
		st[u][i]=st[st[u][i-1]][i-1];
		val[u][i]=min(val[u][i-1],val[st[u][i-1]][i-1]);
	}
	for(Node node:mp[u]){
		int v=node.v;
		if(v==f) continue;
		Dfs(v,u);
	}
}
int Lca(int u,int v){
	int minl=min(dis[Idx(u)][Idy(u)],dis[Idx(v)][Idy(v)]);
	if(dep[u]<dep[v]) swap(u,v);
	for(int i=20;i>=0;i--)
		if(dep[st[u][i]]>=dep[v]){
			minl=min(minl,val[u][i]);
			u=st[u][i];
		}
	if(u==v) return minl;
	for(int i=20;i>=0;i--)
		if(st[u][i]-st[v][i]){
			minl=min(minl,val[u][i]);
			minl=min(minl,val[v][i]);
			u=st[u][i];
			v=st[v][i];
		}
	return minl;
}
void Solve(){
	n=read();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			cin>>ch[i][j];
			sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1];
			if(ch[i][j]=='#')
				sum[i][j]++;
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){
			int l=-1,r=n/2;
			while(l<r-1){
				int mid=l+r>>1;
				if(Check(i,j,mid)) l=mid;
				else r=mid;
			}
			dis[i][j]=2*l+1;
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			for(int k=0;k<=3;k++){
				int x=i+dx[k],y=j+dy[k];
				if(x>=1&&y>=1&&x<=n&&y<=n&&ch[i][j]=='.'&&ch[x][y]=='.')
					e[++tote]={Id(i,j),Id(x,y),min(dis[i][j],dis[x][y])};
			}
	Kruskal();
	for(int i=1;i<=n*n;i++)
		if(!dep[i]&&ch[Idx(i)][Idy(i)]=='.')
			Dfs(i,0);
	int q=read();
	#define y1 Y1
	while(q--){
		int x1=read(),y1=read(),x2=read(),y2=read();
		if(Find(Id(x1,y1))-Find(Id(x2,y2)))
			cout<<"0\n";
		else cout<<Lca(Id(x1,y1),Id(x2,y2))<<"\n";
	}
}
int main(){
	int T=1;
	while(T--) Solve();
	return 0;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...