序列查询新解-CSP202112-2

这篇博客介绍了一种针对202112-1问题的优化解题思路,通过在对f(i)分区间加速计算的基础上对g(x)也进行分区间加速,以降低时间复杂度。博主详细阐述了实现过程,包括记录当前g(x)、next_x和base,以及注意的边界条件,并给出了使用longlong类型和特定输出控制符的细节。最终提供了通过测试的AC代码示例。
摘要由CSDN通过智能技术生成

题目描述

202112-2

解题思路

  • 直接暴力 n n n 复杂度肯定是过不了的
  • 相比202112-1,一种求解思路是在对 f(i) 分区间加速计算的基础上对 g(x) 也进行分区间加速。即在 f(x) 的一个区间之内以 r 为步进进行小区间分区间求解,直到当前 f(x) 段的结束。
  • 实现中可以记录当前的 g(x),需要增加的时候每次增加1即可,记录当前 g(x) 对应的“下一个x”值 next_x,即若超过 next_x 则需要更新 g(x)。同时在每一轮 f(i) 中记录当前计算区间的最小值 base,用于计算下一个小区间长度。
  • 这种思路需要留意边界条件,什么时候对 g(x), next_x和base进行增加,什么时候需要跳出
  • 此外需要注意的细节是需要使用 long long,以及 long long 的输出控制符是 %lld 而不是 %ld。

AC代码

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

int main() {
    int n, N;
    scanf("%d%d", &n, &N);
    int A[n+2];
    A[0] = 0;
    A[n+1] = N; // 省去特判
    for (int i = 1; i <= n; i++) scanf("%d", &A[i]);
    int r = N / (n+1);
    int gx = 0;
    int next_x = r;
    ll sum = 0;
    for (int i = 1; i <= n+1; i++) {
        int base = A[i-1]; // 当前区间左端点值
        while (true) {
            if (A[i] < next_x) {
                sum += (ll)abs((i-1) - gx) * (ll)(A[i] - base);
                break;
            }
            else {
                sum += (ll)abs((i-1) - gx) * (ll)(next_x - base);
                if (A[i] == next_x) break;
                base = next_x;
                next_x += r;
                gx++;
            }
        }
    }
    printf("%lld", sum);
    return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值