【CCF-CSP】 202112-1 序列查询

一、题目

202112-1 序列查询

二、题解

70分
被删掉找不到了XD
思路就是暴力求每个f(i)g(i),做差取绝对值求和。
当时参加考试的我甚至连暴力的方法都没想到,太菜了哈哈哈
100分
#include<bits/stdc++.h>
using namespace std;
const int M = 100010;
int n,N;
int a[M];

int main()
{
    //freopen("C:/Users/Anderson/Desktop/in.txt","r",stdin);
    cin>>n>>N;
    for(int i=1; i<=n; i++){
        cin>>a[i];
    }
    a[n+1] = N;
    a[0] = 0;
    int r = N/(n+1);
    long long sum = 0;
    int cnt_g = 0;
    int temp_r = r;
    for(int i=0; i<=n; i++){
        int f,g;
        int len_f = a[i+1] - a[i];
        if(len_f<temp_r){
            f = i*len_f;
            g = cnt_g*len_f;
            temp_r = temp_r-len_f;
            sum+=abs(g-f);
        }
        else{
            while(len_f){
                if(len_f>=temp_r){
                    f = i*temp_r;
                    g = cnt_g*temp_r;
                    len_f-=temp_r;
                    temp_r = r;
                    cnt_g++;
                    sum+=abs(g-f);
                }
                else{
                    f = i*len_f;
                    g = cnt_g*len_f;
                    temp_r-=len_f;
                    len_f = 0;
                    sum+=abs(g-f);
                }
            }
        }
    }
    cout<<sum;
}

其实冷静一下,这道题很好做,甚至用不上什么算法。
题目中对于70%的数据 1<=n<=200;n<N<=1000那么暴力遍历1到N并循环求f是1到n,时间最多也就2e5,完全没问题。但对于后30%的数据采用暴力时间对多到了1e14,肯定是超了。
那要怎么优化呢?其实第一题就给了我们提示,只需要按照第一题的思路,将挨个求f,g变成求部分sum之后再相减即可,这样我们只需要循环从1到n而非N。过程中需要注意的是怎样去分段,不能因为我们是从1到n循环,所以直接按照数组两两相邻的子区间分段。因为很有可能f的值在这个区间既有大于g的,也有小于g的,导致结果错误。
所以过程中我们还要按照r的值再进行分段,每计算了r个值,就需要更新g的值。经过这样的分段,每段中g的值和f的值都一定是不变的,再求g和f的sum时就一定不会出现上面提到的情况了。
不过还有一个问题就是复杂度,因为还要根据r分段,所以一共是有两次循环的,有没有可能超时呢?其实做的时候我并没有仔细分析这个问题,只是感觉时间变少了,所以尝试了一下。不过仔细分析,结果也是明了的。n的范围1–1e5。最外层循环从1–n,而内层循环最复杂的情况也就是N/r也就是n+1。时间复杂度就是 O ( n 2 ) O(n^2) O(n2)。根据n的范围,最多也就1s,刚好符合条件,况且实际数据肯定复杂度更小。

还遇到一个问题就是sum的值可能很大,类型应该是long long,不过出题人也很贴心,最后给了提示。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值