#C240218C. 塔


#C240218C. 塔

前言(Front talk)

由于题目中给的是,所以根本没有往的时间复杂度去想,结果……

数据太水,正解就是。(*  ̄︿ ̄)

网址(Website)

题目详情 - 塔 - Super

题解 - 塔 - Super

题解(Solution)

由于出现最大和最小,第一时间就想到了二分答案,但是考试时认为过不了 ,所以就根本没在往后面想了。

计算得可以直接求出每两个塔之间的距离,并且存下来。

二分中的是两组塔距离的上限,如果两塔之间的距离大于,那么这两个塔一定不在同一个组内,于是可以将两个塔的编号连边。由于只有两个组,我们可以用二分图的判定来判断此时的是否满足条件。

由于当前的二分图不一定是全联通,因此这个联通块里面的塔可以放在左边或者放在右边,因此最后的方案数就是2的连通块个数次方。

代码(Code)

#include<bits/stdc++.h>
#include<queue>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define P pair<int,int>
#define int long long
inline int input(){int x;return cin>>x,x;}
const int inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const int N = 5005;

bool ST;

int d[N][N];
int n,ans;
P tow[N];

int col[N],sum;
bool check(int mid){
	memset(col,0,sizeof col);
	queue<int> q;sum=0;
	For(i,1,n){
		if(col[i]) continue;
		q.emplace(i);col[i]=1;
		while(q.size()){
			int x=q.front();q.pop();
			For(y,1,n){
				if(d[x][y]<=mid) continue;
				
				if(col[y]==col[x]){
					return false;
				}else if(!col[y]) col[y]=3-col[x],q.emplace(y);
			}
		}sum++;
	}return true;
}

inline int ksm(int x,int k){
	int res=1;while(k){
		if(k&1) res=res*x%mod;
		x=x*x%mod,k>>=1;
	}return res;
}

bool ED;
inline int get_dis(P x,P y){return abs(x.first - y.first) + abs(x.second - y.second);}
signed main(){
	ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
	string str("tower");
	freopen((str+".in").c_str(),"r",stdin);
	freopen((str+".out").c_str(),"w",stdout);
	cerr<<abs(&ST-&ED)/1024./1024.<<"MB\n";
	cin>>n;int Tim = clock();
	For(i,1,n) tow[i]={input(),input()};
	
	{//求得每个点之间的距离 
		For(i,1,n) For(j,1,n){
			d[i][j] = get_dis(tow[i],tow[j]);
		}
	}
	
	{//二分求得最小距离 
		int l=0,r=10000,mid;
		while(l<=r){
			mid = (l+r)>>1;
			if(check(mid)) r=mid-1,ans=mid;
			else l=mid+1;
		}check(ans);
	}
	
	cout<<ans<<'\n'<<ksm(2,sum)<<'\n';
	return cerr<<"TIME:"<<(clock()-Tim)/1000.,0;
}

文章作者: WolfDeer
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 WolfDeer !
  目录