ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 星空

2021-08-16 06:31:50  阅读:137  来源: 互联网

标签:head 星空 int 题解 ll 距离 define size


传送门

  • 遇到形如 \(| |x_1-x_2| \pm |y_1-y_2| |\) 的柿子,一定要注意是不是可以转化为切比雪夫距离求解!

考试的时候只想到 \(n^2\) 做法,先并查集维护距离为零的点,再枚举点对更新距离
这个做法的复杂度瓶颈在于枚举点对求最小距离的过程
发现题面里给的柿子类似曼哈顿距离,只能先确定这两个点再求
尝试转化为切比雪夫距离的变式,则这里变成了取min
而我们恰好要求最小距离,这就很可做了
同样并查集处理,按横,纵坐标分别排序后再枚举相邻的点更新最小距离
然后再同样分别排序后再扫一遍相邻点,在能取到最小距离的点所属并查集间连边
最后扫描这些并查集统计答案即可

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 9187201950435737471ll
#define N 100010
#define ll long long 
#define pb push_back
//#define int long long 

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
ll x[N], y[N];
int head[N], size;
struct edge{int to, next; ll val;}e[300*350];
inline void add(int s, int t, ll w) {e[++size].to=t; e[size].val=w; e[size].next=head[s]; head[s]=size;}

namespace force{
	ll minn=4557430888798830399ll, dis[N], cnt;
	bool vis[N];
	void spfa(int s) {
		memset(dis, 0x3f, sizeof(ll)*(n+5));
		dis[s]=0;
		queue<int> q;
		q.push(s);
		int u;
		while (q.size()) {
			u=q.front(); q.pop();
			vis[u]=0;
			for (int i=head[u],v; ~i; i=e[i].next) {
				v = e[i].to;
				if (dis[v] > dis[u]+e[i].val) {
					dis[v] = dis[u]+e[i].val;
					if (!vis[v]) q.push(v), vis[v]=1;
				}
			}
		}
	}
	void solve() {
		memset(head, -1, sizeof(head));
		ll d;
		for (int i=1; i<=n; ++i) 
			for (int j=i+1; j<=n; ++j) {
				d = llabs(llabs(x[i]-x[j])-(llabs(y[i]-y[j])));
				//if (d) minn=min(minn, d);
				add(i, j, d), add(j, i, d);
			}
		//cout<<"minn: "<<minn<<endl;
		for (int i=1; i<=n; ++i) {
			spfa(i);
			for (int j=1; j<=n; ++j) {
				if (dis[j]==minn) ++cnt;
				else if (dis[j] && dis[j]<minn) {
					minn=dis[j], cnt=1;
				}
			}
		}
		if (minn>=4557430888798830399ll) {puts("-1"); exit(0);}
		printf("%lld\n%lld\n", minn, cnt/2);
		exit(0);
	}
}

namespace task1{
	ll ans=INF, cnt;
	int fa[N], tot, lst[N], siz2[N], siz3[N];
	ll mp[2010][2010];
	struct edge{int from, to, next; ll val;}e[2010*2010];
	inline void add(int s, int t, ll w) {e[++size].to=t; e[size].from=s; e[size].val=w; e[size].next=head[s]; head[s]=size;}
	inline int find(int p) {return fa[p]==p?p:fa[p]=find(fa[p]);}
	void solve() {
		memset(head, -1, sizeof(head));
		memset(mp, 127, sizeof(mp));
		//cout<<ans<<' '<<mp[1][1]<<endl;
		for (int i=1; i<=n; ++i) fa[i]=i;
		for (int i=1; i<=n; ++i) siz2[i]=1;
		ll d;
		for (int i=1,f1,f2; i<=n; ++i) 
			for (int j=i+1; j<=n; ++j) {
				f1=find(i), f2=find(j);
				if (f1==f2) continue;
				d = llabs(llabs(x[i]-x[j])-(llabs(y[i]-y[j])));
				if (!d) fa[f2]=f1, siz2[f1]+=siz2[f2]; //, cout<<"uni: "<<i<<' '<<j<<' '<<siz2[f1]<<' '<<siz2[f2]<<endl;
				add(i, j, d);
			}
		for (int i=1,f1,f2; i<=size; ++i) {
			f1=find(e[i].from), f2=find(e[i].to);
			if (f1==f2) continue;
			if (!lst[f1]) lst[f1]=++tot, siz3[tot]=siz2[f1];
			if (!lst[f2]) lst[f2]=++tot, siz3[tot]=siz2[f2];
			mp[lst[f1]][lst[f2]]=min(mp[lst[f1]][lst[f2]], e[i].val);
			mp[lst[f2]][lst[f1]]=min(mp[lst[f2]][lst[f1]], e[i].val);
		}
		//cout<<"tot: "<<tot<<endl;
		//cout<<"siz: "; for (int i=1; i<=tot; ++i) cout<<siz3[i]<<' '; cout<<endl;
		for (int i=1; i<=tot; ++i) 
			for (int j=i+1; j<=tot; ++j) {
				if (mp[i][j]<INF) {
					if (mp[i][j]==ans) cnt+=siz3[i]*siz3[j]; //, cout<<"+="<<siz3[i]<<' '<<siz3[j]<<endl;
					else if (mp[i][j]<ans) {
						ans=mp[i][j];
						cnt=siz3[i]*siz3[j]; //, cout<<"recover: "<<siz3[i]<<' '<<siz3[j]<<endl;
					}
				}
			}
		if (ans==INF) {puts("-1"); exit(0);}
		printf("%lld\n%lld\n", ans, cnt);
		exit(0);
	}
}

namespace task{
	ll ans=INF, cnt;
	int fa[N], tot, lst[N], siz[N];
	vector<int> e[N];
	struct point{ll x, y; int rk; inline void build(ll x_, ll y_, int r_) {x=x_; y=y_; rk=r_;}}p[N];
	inline bool cmp1(point a, point b) {return a.x<b.x;}
	inline bool cmp2(point a, point b) {return a.y<b.y;}
	inline int find(int p) {return fa[p]==p?p:fa[p]=find(fa[p]);}
	void solve() {
		for (int i=1; i<=n; ++i) p[i].build(x[i]+y[i], x[i]-y[i], i);
		for (int i=1; i<=n; ++i) fa[i]=i;
		for (int i=1; i<=n; ++i) siz[i]=1;
		ll d;
		sort(p+1, p+n+1, cmp1);
		for (int i=2,f1,f2; i<=n; ++i) 
			if (p[i].x==p[i-1].x) {
				if (f1=find(p[i].rk),f2=find(p[i-1].rk),f1!=f2) 
					fa[f1]=f2, siz[f2]+=siz[f1];
			}
			else {
				d=min(llabs(p[i].x-p[i-1].x), llabs(p[i].y-p[i-1].y));
				if (d) ans=min(ans, d);
			}
		sort(p+1, p+n+1, cmp2);
		for (int i=2,f1,f2; i<=n; ++i) 
			if (p[i].y==p[i-1].y) {
				if (f1=find(p[i].rk),f2=find(p[i-1].rk),f1!=f2) 
					fa[f1]=f2, siz[f2]+=siz[f1];
			}
			else {
				d=min(llabs(p[i].x-p[i-1].x), llabs(p[i].y-p[i-1].y));
				if (d) ans=min(ans, d);
			}
		
		sort(p+1, p+n+1, cmp1);
		for (int i=2; i<=n; ++i) 
			if (p[i].x!=p[i-1].x && min(llabs(p[i].x-p[i-1].x), llabs(p[i].y-p[i-1].y))==ans) 
				e[find(p[i-1].rk)].pb(find(p[i].rk)), e[find(p[i].rk)].pb(find(p[i-1].rk));
		sort(p+1, p+n+1, cmp2);
		for (int i=2; i<=n; ++i) 
			if (p[i].y!=p[i-1].y && min(llabs(p[i].x-p[i-1].x), llabs(p[i].y-p[i-1].y))==ans) 
				e[find(p[i-1].rk)].pb(find(p[i].rk)), e[find(p[i].rk)].pb(find(p[i-1].rk));
		if (ans==INF) {puts("-1"); exit(0);}
		for (int i=1,sz; i<=n; ++i) if (e[i].size()) {
			sort(e[i].begin(), e[i].end());
			sz=unique(e[i].begin(), e[i].end())-e[i].begin();
			e[i].resize(sz);
			for (auto it:e[i]) cnt+=siz[i]*siz[it];
		}
		printf("%lld\n%lld\n", ans, cnt/2);
		exit(0);
	}
}

signed main()
{
	n=read();
	for (int i=1; i<=n; ++i) x[i]=read(), y[i]=read();
	//if (n<=300) force::solve();
	//else task1::solve();
	task::solve();
	
	return 0;
}

标签:head,星空,int,题解,ll,距离,define,size
来源: https://www.cnblogs.com/narration/p/15145902.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有