2021 7.24 模擬測試 2.友好的序列
阿新 • • 發佈:2021-07-25
描述
在資訊競賽班的一次歡樂活動中,為了增強友誼,同學們站成了一列,編號從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; }