1. 程式人生 > 其它 >2021 7.24 模擬測試 2.友好的序列

2021 7.24 模擬測試 2.友好的序列

描述

在資訊競賽班的一次歡樂活動中,為了增強友誼,同學們站成了一列,編號從1到n。每個人 手上都有一個球,球上有一個數字。遊戲規定對於任意兩個人(i,j),他們的友好度為(i-j)2+g(i,j)2,其中g(i,j)= ∑ jk=i+1a[k]
請你幫助老師計算出任意兩個人的最小可能友好度是多少?

輸入

第一行1個整數 接下來一行是N個整數,表示每個人手上球上的數字。

輸出

輸出 1個整數表示最小的友好度

輸入樣例

4
1 0 0 -1

輸出樣例

1

【資料規模和約定】

40%的資料保證:
100%的資料保證:

題解

正解

設s[i]為字首和,g(i,j)即為sum[j]-sum[i]
問題變為求平面內最近點對
1、選取一垂直線l:x=m 來作為分割直線。其中 為 中各點x座標的中位數。由此將S分割為S1和S2。
2、遞迴地在S1和S2上找出其最小距離d1和d2,並設d=min{d1,d2},S中的最接近點對或者是d,或者是某個{p,q},其中p∈P1且q∈P2。最後列舉區間間點對。

非正解

這個竟然可以n2,加一步剪枝即可
列舉每個點,若當前(i-j)2>ans,由於(sum[i]-sum[j])2>0
則直接停止搜尋

程式碼

非正解

#include<bits/stdc++.h>
using namespace std;
#define pf(x,y) (x-y)*(x-y)
#define int long long
#define in read()
inline int read()
{
    int data=0;int w=1; char ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return data*w;
}
int n,a[100005],sum[100005],ans=1e18;
int dist(int x,int y)
{
	int ret=pf(x,y);
	if(ret>ans) return -1;
	return ret;
}
signed main()
{
	n=in;
	for(int i=1;i<=n;i++) a[i]=in,sum[i]=sum[i-1]+a[i];
	for(int i=1;i<n;i++)
		for(int j=i+1;j<=n;j++)
		{
			int ret=dist(i,j);
			if(ret==-1) break;
			int g=pf(sum[i],sum[j]);
			ans=min(ans,g+ret);
		}
	cout<<ans;
}

正解

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define in read()
inline int read()
{
    int data=0;int w=1; char ch=getchar();
    while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
    if(ch=='-') w=-1,ch=getchar();
    while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
    return data*w;
}
const int N=1e5+10;
int q[N],k;
struct node{int x;ll y;}p[N];
bool cmp1(node a,node b){return a.x<b.x;}
bool cmp2(node a,node b){return a.y<b.y;}
ll dis2(int a,int b){return (ll)(p[a].x-p[b].x)*(p[a].x-p[b].x)+(ll)(p[a].y-p[b].y)*(p[a].y-p[b].y);}
ll solve(int l,int r)
{
	if(l==r)return 1e18;
	int mid=l+r>>1;
	ll d2=min(solve(l,mid),solve(mid+1,r));
	inplace_merge(&p[l],&p[mid+1],&p[r+1],cmp2);
	k=0;
	double d=sqrt(d2);
	for(int i=l;i<=r;++i)
		if(fabs(p[mid].x-p[i].x)<d)
			q[++k]=i;
	for(int i=1;i<=k;++i)
		for(int j=i+1;j<=k&&p[q[j]].y-p[q[i]].y<d;++j)
			d2=min(d2,dis2(q[i],q[j]));
	return d2;
}
signed main()
{
	freopen("b.in","r",stdin);
	freopen("b.out","w",stdout);
	n=in;
	for(int i=1,w;i<=n;++i)
	{
		a[i]=in,sum[i]=sum[i-1]+a[i];
		p[i].x=i,p[i].y=p[i-1].y+a[i];
	}
		sort(p+1,p+n+1,cmp1);
		cout<<solve(1,n);
	return 0;
}