列表

详情


NC25107. 小w的基站网络

描述

W城有n座基站,每座基站可用一个二维特征向量来表示,并且任意一座基站的特征向量均满足y>0。任意两座基站之间是否有单向传输数据的专线取决于这两座基站特征向量的叉积,当且仅当时,有一条从a基站到b基站传输数据的单向专线,专线的传输代价为这两座基站的叉积。反之如果,则代表不能从a基站向b基站传输数据。

对于两个二维向量

每一座基站都可以传输数据和接收数据,所以当你需要从基站u向基站v传输数据时,不但可以通过u到v的单向专线(如果存在的话)直接传输数据,同时也可以先向其他基站传输数据,然后在整个基站网络的传播下到达基站v。这样的代价为经过的所有专线的代价之和。
小w在其中的第k个基站工作,他想知道他所在的基站向其他基站传输数据的最小代价各是多少。

输入描述

第一行输入一个正整数n表示有座基站。

接下来n行,每行两个整数x,y表示每个基站的特征向量,并且保证所有的特征向量均满足

最后输入一个正整数k

表示小w所在的基站。

输出描述

输出共n行,依次表示小w所在的基站向各个基站传输数据的最小代价。如果小w所在的基站无法到达目标基站,则在该行输出一个"-1"来表示无法到达。

示例1

输入:

5
-1 1
-1 5
1 5
0 2
2 2
5

输出:

4
6
8
4
0

说明:

如图所示,小w所在的基站为5号基站

示例2

输入:

5
-1 1
-1 5
1 5
0 2
2 2
1

输出:

0
-1
-1
-1
-1

说明:

如图所示,小w所在的基站为1号基站。
由于1号基站没有出边,所以除了到自己的最小代价为0,无法到达其他基站。

示例3

输入:

5
-2 2
2 2
1 1
-1 1
1 1
3

输出:

4
-1
0
2
-1

说明:

如图所示,小w所在的基站为3号基站,注意3号基站与2号5号基站的特征向量的叉积为0,所以没有边相连。
同理1号基站与4号基站也无边相连。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 806ms, 内存消耗: 40532K, 提交时间: 2020-02-01 19:49:13

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
int stk[N],top;
ll dp[N];
struct node
{
	ll x,y;
	int id;
}a[N];
//极角排序
bool cmp(node a,node b)
{
	ll tmp=a.x*b.y-a.y*b.x;
	if(tmp)
		return tmp>0;
	return a.x*a.x+a.y*a.y>b.x*b.x+b.y*b.y;
}

ll cross(node a,node b)
{
	return a.x*b.y-a.y*b.x;
}

int main()
{

	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&a[i].x,&a[i].y);
		a[i].id=i;
	}
	sort(a+1,a+1+n,cmp);
	int flag,st;
	scanf("%d",&st);
	memset(dp,-1,sizeof dp);
	dp[st]=0;
	for(int i=1;i<=n;i++)
	{
		if(a[i].id==st)
		{
			flag=i;
			break;
		}
	}
	stk[++top]=flag;
	for(int i=flag+1;i<=n;i++)
	{
		if(cross(a[flag],a[i])==0) continue;
		while(top>1&&cross(a[stk[top-1]],a[stk[top]])==0)top--;
		while(top>1&&dp[a[stk[top]].id]+cross(a[stk[top]],a[i])>=dp[a[stk[top-1]].id]+cross(a[stk[top-1]],a[i]))--top;
		dp[a[i].id]=dp[a[stk[top]].id]+cross(a[stk[top]],a[i]);
		stk[++top]=i;
	}
	for(int i=1;i<=n;i++)
		printf("%lld\n",dp[i]);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 766ms, 内存消耗: 28804K, 提交时间: 2019-06-21 21:14:52

#include<bits/stdc++.h>
#define fo(i,a,b)for(int i=a,_e=b;i<=_e;++i)
#define fd(i,a,b)for(int i=b,_e=a;i>=_e;--i)
#define nod(x,y) (nod){x,y}
#define ll long long
using namespace std;
const int N=1e6+5;
int n,k;
int st[N],ss;
ll ans[N],p[N];
struct nod{
	int x,y,i;
}b[N];
ll cj(nod a,nod b){
	return (ll)a.x*b.y-(ll)a.y*b.x;
}
bool cmp(nod x,nod y){
	ll t=cj(x,y);
	return t>0||t==0&&x.y>y.y;
}
bool pd(nod x,nod y,nod z){
	nod X=(nod){x.x-y.x,x.y-y.y},Y=(nod){z.x-y.x,z.y-y.y};
	return cj(X,Y)<=0;
}
int main(){
	scanf("%d",&n);
	fo(i,1,n){
		scanf("%d%d",&b[i].x,&b[i].y);
		b[i].i=i;ans[i]=-1;
	}
	scanf("%d",&k);
	stable_sort(b+1,b+n+1,cmp);
	bool go=0;
	fo(i,1,n){
		if(b[i].i==k){
			st[ss=1]=i;
			ans[k]=0;
			go=1;
			continue;
		}
		if(!go)continue;
		if(cj(b[st[1]],b[i])==0)continue;
		for(;ss>1&&pd(b[st[ss-1]],b[st[ss]],b[i]);)--ss;
		st[++ss]=i;
		ans[b[i].i]=p[ss]=p[ss-1]+cj(b[st[ss-1]],b[st[ss]]);
	}
	fo(i,1,n)printf("%lld\n",ans[i]);
}

上一题