Logo Will.Pam的博客

博客

模拟赛B题-找朋友(friend)—题解

2023-05-03 17:59:03 By Will.Pam

#12865. 找朋友(friend)

70分做法:不少人都得了70分,思路很简单,分两种情况讨论

1.编号小的到编号大的
2.编号大的到编号小的(因为小朋友们围成了一个圈)

70分代码:

#include<bits/stdc++.h>
using namespace std;    
int n,a[10005],sum=0;
void solve(){
    int xx,yy;
    cin>>xx>>yy;
    int x=min(xx,yy),y=max(xx,yy);
    int sum1=0,sum2=0;
    for(int i=x;i<y;i++){
        sum1+=a[i];
    }
    sum2=sum-sum1;
    sum1*=(y-x);
    x+=n;
    sum2*=(x-y);
    cout<<min(sum1,sum2)<<endl;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        sum+=a[i];
    }
    int k;
    cin>>k;
    while(k--){
        solve();
    }
    return 0;
}

但令人悲伤的是:

对于 100% 的数据, 满足 n<=10000, k<=1000000

而上面的做法复杂度为O(nk),妥妥的TLE!

所以我们需要对此进行优化

其中有k组数据所以要循环k次,这是不可以省略的

所以我们只能优化O(n)的循环

-------------------------------------------------分界线-------------------------------------------------------

此处强烈建议食用前缀和

先跳脱出小朋友围成一圈的情境

举个栗子:

编号  1  2  3  4  5

数值  10 20 30 40 50

题目中我们要求的是从一个编号到另一个编号数值之和

比如:

求编号3-5的数值之和

刚才我们用了循环累加法

需要耗费O(n)的复杂度

但是我们可以先将1-5的数值和算出来

再减去1-2的数值和

就能快速得出3-5的数值和了

不信?验算一下:

1-5:10+20+30+40+50=150

1-2:10+20=30

3-5:30+40+50=120

而150-30=120

所以可以得出规律:

x-y的数值和=1-y之和减去1-(x-1)的和

这样只需要在输入时每次统计一边=遍前缀和(即这个位置到第一个位置的权值和)

每次计算使用即可,一劳永逸!

注意点:

1.输入的x和y不一定有序,需要手动确保有序

2.开long long + printf + scanf

3.x,y在计算前都要-1

AC主代码:

long long sum1=(dis[y]-dis[x])*(y-x);
long long sum2=(dis[n]-dis[y]+dis[x])*(x+n-y);

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。