~5 ccf 2021-12-2 序列查询新解

题目描述

在这里插入图片描述

输入

在这里插入图片描述

输出

在这里插入图片描述

样例输入

样例1

3 10
2 5 8

样例2

9 10
1 2 3 4 5 6 7 8 9

样例3

2 10
1 3

样例输出

样例1

5

样例2

0

样例3

6

子任务

在这里插入图片描述

源代码

70分:

#include <iostream>
#include <math.h>
using namespace std;

int main (){
    int  n,N;
    cin>>n>>N;

    long double *f=new long double [N+1];
    long double *g=new long double [N+1];
    long double *t=new long double [N+1];
    long double *c=new long double [N+1];

    int   rate=0;
    int   temp=0;
    int   i=0;
    int   result=0;
    int   h=0;
    int   count=0;
    int   k=0;
    f[0]=0;
    g[0]=0;
    c[0]=0;
    t[0]=0;
    for (i = 1; i <=n ; i++) {
        cin>>temp;
        t[i]=temp;
        c[i-1]=t[i]-t[i-1];
    }
    c[i-1]=N-t[i-1];
    rate=ceil((double )(N/(n+1)));
    for (int j = 0; j < N; j++) {
        g[j]= ceil((double )(j/rate));
    }

    for (int j = 0; j < N; j++) {
        if (c[h]!=count){
            count++;
        }
        else{
            h++;
            k++;
            count=1;
        }
        f[j]=abs(g[j]-k);
    }
    for (int j = 0; j <N ; j++) {
        result+=f[j];
    }
    cout<<result<<endl;
    return 0;
}

100分:

#include <iostream>
#include <cmath>
using namespace std;
#define ll long long

// 求f数列某个区间的值。x表示区间的右边界开区间,y表示左边界闭区间,i表示区间内的任意元素值为i
ll getFSum(int x, int y, int i) {
    return (ll)(x - y) * i;
}

// 计算g数列前pos项的和
ll getGSum(int pos, int r) {
    int st = 0;
    // 前pos项中完整长度为r的区间的个数
    int seqNum = (pos + 1) / r;
    // 前pos项中最后一个不完整区间的个数,为0或1
    int lastSeqNum = (pos + 1) % r == 0 ? 0 : 1;
    // 千seqNum个区间的区间和
    ll sum = (ll)seqNum * (seqNum - 1) / 2 * r;
    // 最后一个区间中的值的和
    ll lastSum = (ll)seqNum * lastSeqNum * ((pos + 1) % r);
    return sum + lastSum;
}

// 计算yx区间内g-f的绝对值
ll getSum(int x, int y, int r, int i) {
    int f, gMin, gMax, changedIndex;
    ll sum = 0;
    f = i;
    gMin = y / r;
    gMax = (x - 1) / r;
    if(f >= gMax)
        sum += getFSum(x, y, i) - (getGSum(x - 1, r) - getGSum(y - 1, r));
    else if(f <= gMin)
        sum += (getGSum(x - 1, r) - getGSum(y - 1, r)) - getFSum(x, y, i);
    else {
        for(int k = gMin; k <= gMax; k ++)
            if(k >= i) {
                changedIndex = y + (k - gMin) * r;
                sum += getFSum(changedIndex, y, i) - (getGSum(changedIndex - 1, r) - getGSum(y - 1, r));
                sum += (getGSum(x - 1, r) - getGSum(changedIndex - 1, r)) - getFSum(x, changedIndex, i);
                break;
            }
    }
    return sum;
}

int main() {
    int n, N, x = 0, y, r;
    ll sum = 0;
    cin >> n >> N;
    r = N / (n + 1);

    for(int i = 0; i < n; i ++) {
        y = x;
        cin >> x;
        if(x > y)
            sum += getSum(x, y, r, i);
    }

    // 最后计算xN区间
    sum += getSum(N, x, r, n);

    cout << sum;
}

关于这题

70分 其实都是int 也是70分…

100分: 还是换个思路 不再计算每个的值 再计算 |f(i)-g(i)| 而是计算 一整个区间的|f(i)-g(i)|的值
g(i)的每r个数的值是一样的(可能存在最后的几个数 ,不足r个数,这个要单独讨论)
既然是要计算整个区间的值,去绝对值,就分两种情况,f(i)>=g(i) 和 f(i)<g(i)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值