题目




样例


思路: 前缀和思想

观察f(x)f(x)f(x)和g(x)g(x)g(x)的序列,其实是有规律的:

  • f(x)f(x)f(x)在每个A[i]A[i]A[i]处+1+1+1,在[A[i],A[i+1])[A[i],A[i+1])[A[i],A[i+1])中值相等
  • 当x>=A[n]x>=A[n]x>=A[n]时,f(x)=nf(x)=nf(x)=n
  • g(x)g(x)g(x)每rrr个数+1+ 1+1
    因为由g(x)g(x)g(x)定义可知:

    g(x)g(x)g(x)中xxx每经过rrr个数会+1+1+1

所以整体思路可以先对序列A进行遍历,每次遍历一个f(i)f(i)f(i)相等的区间,在这个相等的区间里,fff函数值是相同的,再去处理ggg函数。

将最大的值NNN加入到序列A的后面,这样序列A的每两个相邻的数,都是一段f(i)f(i)f(i)相等的区间,且在这段区间里的f(i)f(i)f(i)值等于区间的左边界值。
对于每个这样的区间,ggg函数的值与fff函数的值有三种关系:
由ggg函数是单调不减函数,可知:

  • 1.右边界r<左边界(f的值)\frac{右边界}{r}<左边界(f的值)r右边界​<左边界(f的值):此时ggg函数的值在区间内恒小于fff函数的值
  • 2.左边界r>左边界(f的值)\frac{左边界}{r}>左边界(f的值)r左边界​>左边界(f的值):此时ggg函数的值在区间内恒大于fff函数的值
  • 3.ggg函数在区间内递增,且有一个位置等于左边界(f的值)左边界(f的值)左边界(f的值),在这个位置的左边,ggg函数的值小于fff函数的值;在这个位置的右边,ggg函数的值大于fff函数的值

对于情况一:直接拿区间内f值的和 减去 区间内g值的和
对于情况二:直接拿区间内g值的和 减去 区间内f值的和
对于情况三:在相等点的左右两侧,分别拿大的和 减去 小的和

在区间内fff函数的和是易求的,因为值固定,而在区间内ggg函数的和是难求的,可以求出其前缀和。

如何计算ggg的前缀和?
我们可以看出g(i)g(i)g(i)的前kkk(这里kkk从000开始)项,是由rrr个首项为000、项数为(k+1)/r(k + 1) / r(k+1)/r、公差为111的等差数列,以及(k+1)%r(k + 1) \% r(k+1)%r个k/rk / rk/r构成的。
那么我们可以知道h(i)=r×0+(i+1r−1)2×i+1r+(i+1)%r×irh(i)=r\times\frac{0+(\frac{i+1}{r}-1)}{2}\times\frac{i+1}{r}+(i + 1) \% r\times\frac{i}{r}h(i)=r×20+(ri+1​−1)​×ri+1​+(i+1)%r×ri​。
因此当我们要计算[l,r][l,r][l,r]范围内的g(i)g(i)g(i)的和时,可得:sum=h[r]−h[l−1]sum=h[r]-h[l-1]sum=h[r]−h[l−1]
而这时间复杂度几乎是O(1)O(1)O(1)的。


代码

为了数据不越界,都采用long long类型

#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long LL;LL h(LL i,LL r) //求g(i)的前缀和h(i)
{ if(i<0) return 0;else return r*((i+1)/r-1)*((i+1)/r)/2+(i+1)%r*(i/r);
}
LL cal(LL fi,LL lft,LL rgt,LL r)//给定一个f(i),计算区间里的|g(i)-f(i)|之和,前提是g(i)全部小于等于或者全部大于等于f(i)
{ return abs(h(rgt,r)-h(lft-1,r)-fi*(rgt-lft+1));
}
int main()
{LL n,N,t;scanf("%lld%lld",&n,&N);vector<LL> a;a.push_back(0);//默认A[0]=0 for(int i=0;i<n;++i) {scanf("%lld",&t);a.push_back(t);}a.push_back(N);   //把N加到末尾LL r=N/(n+1),ans=0;   //计算出r,ans存储结果 for(LL fi=0;fi<=n;++fi)  //遍历序列A中的每个数,从位置0遍历到位置n,fi表示的是f值得左边界,当遍历到n时,f的值是最大的 { //遍历每个f(i)LL lft=a[fi],rgt=a[fi+1]-1;   //左边界为a[fi],右边界为a[fi+1]-1,在这个范围内的f值都为fi if(lft/r>=fi||rgt/r<=fi) ans+=cal(fi,lft,rgt,r); //如果区间内g(i)全部小于等于或者全部大于等于f(i),直接使用cal函数else ans+=cal(fi,lft,r*fi,r)+cal(fi,r*fi+1,rgt,r); //否则将区间分成两半,分别使用cal函数}printf("%lld",ans);return 0;
}

在计算前缀和的函数里为什么不能再对式子进行化简?
因为把中间过程的除法化简掉可能发生溢出。


更简洁的解法

参考:https://blog.csdn.net/LarsGyonX/article/details/122857350

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
int n,N,a;
int main()
{scanf("%d%d",&n,&N);vector<int> A;A.push_back(0);for(int i=1;i<=n;i++){scanf("%d",&a);A.push_back(a);}A.push_back(N);LL res=0;int r=N/(n+1);int gnext=r,gx=0;//gnext是下一个g函数的变化点,开区间for(int i=1;i<=n+1;i++) //遍历A,对每个相等的f区间,再用g来对它进一步划分{int left=A[i-1];  //很重要while(true){if(A[i]<=gnext)  //g在f这个大区间内已经不变{res+=(LL)abs(i-1-gx)*(LL)(A[i]-left);  //直接算值break;}else   //g在f的不变区间内是可变的{res+=(LL)abs(i-1-gx)*(LL)(gnext-left);   //先把前面一部分不变的给算上left=gnext;  //更新左边界,闭区间gnext+=r;  //更新新的变化点gx++;    //更新gx的值}}}printf("%lld",res);return 0;
}

csp202112-2:序列查询新解 题解相关推荐

  1. CCF-CSP-202112-2:序列查询新解(C++11题解)

    文章目录 问题描述 解题思路 AC代码 问题描述 题目来源:CCF-CSP-202112-2:序列查询新解 解题思路 思路稍后再补. AC代码 PA了一次,是因为没开long long #includ ...

  2. CCF CSP202112-2 序列查询新解

    CCF CSP202112-2 序列查询新解 题目背景 上一题"序列查询"中说道: A=[A0,A1,A2,⋯,An]A=[A_0,A_1,A_2,⋯,A_n]A=[A0​,A1​ ...

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

    序列查询新解 题目描述 输入 输出 样例输入 样例输出 子任务 源代码 关于这题 题目描述 输入 输出 样例输入 样例1 3 10 2 5 8 样例2 9 10 1 2 3 4 5 6 7 8 9 样 ...

  4. CCF CSP 序列查询新解

    CCF CSP 序列查询新解(C语言) 题目背景 上一题"序列查询"中说道: A=[A0,A1,A2,⋯,An] 是一个由 n+1 个 [0,N) 范围内整数组成的序列,满足 0= ...

  5. CSP CCF: 202112-2 序列查询新解 (C++)

    题目链接:计算机软件能力认证考试系统 试题编号: 202112-2 试题名称: 序列查询新解 时间限制: 1.0s 内存限制: 512.0MB 题目背景 上一题"序列查询"中说道: ...

  6. CCF-CSP 202112-2 序列查询新解

    题目:序列查询新解 思路:在f区间内划分g区间,注意g区间左端点的定值,不断移动g区间(长度都为r),当g区间末端点超出f的范围,进入下一个f循环 #include<bits/stdc++.h& ...

  7. CCF 202112-2 序列查询新解 python 满分

    CCF 202112-2 序列查询新解 python 满分 题目叙述 问题描述:略 输入格式:略 输出格式:略 样例 满分证明 解题思路 01Python超时70分 02满分python思路 第一,计 ...

  8. CCF CSP 202112-2 序列查询新解

    单纯地讲思路有些难懂,这里结合一个实际例子来说明: 我们假设A = {0,1,3},n = 2,N = 10,r = 10 / (2 + 1) = 3. i 0 1 2 3 4 5 6 7 8 9 f ...

  9. CCF202112-2 序列查询新解

    问题描述: 解题思路: 解题代码:C++11代码 #include <bits/stdc++.h> using namespace std;long long h(long long i, ...

最新文章

  1. Mac OS X的快捷键
  2. ant design后台模板-1.前端环境搭建
  3. 再谈新浪微博架构——视频观后笔记
  4. 项目中用到的BAPI合集
  5. the day of python learning(考试解释)
  6. php如何转类型,PHP数据类型转换
  7. IE8下强制浏览器用哪个IE版本渲染页面
  8. 多项式拟合lm_R语言多项式回归
  9. android手机 环境变量 文件,【图片】【教程】配置安卓Java环境变量【手机端反编译吧】_百度贴吧...
  10. 分布式系统最终一致性
  11. [转载] python numpy--矩阵的通用函数
  12. java发送带附件的邮件_Java发送邮件(带附件)
  13. C语言——指针详解(必收藏)
  14. 【SSM分布式架构电商项目-32】Dubbo入门
  15. 我的世界1.12.2java下载_我的世界1.12.2.2中文版下载 我的世界1.12.2.2中文版单机游戏下载...
  16. CAD,SolidWorks相比ProE,UG等软件有什么区别?怎么下载?
  17. 运营小技能:订阅号文章排版教程(添加图片超链接、推文采集、往期推荐)
  18. C语言内存空间分布详解
  19. 好的设计的10个原则
  20. 微信域名防封的注意点,微信域名防封系统原理

热门文章

  1. linux prompt模式,Linux修改prompt提示的方法 | Soo Smart!
  2. xbox360游戏下载_完成的乐趣-通过Xbox向后兼容性探索旧游戏
  3. 帮公司面试了一个30岁培训班出来的程序员,没啥工作经验...
  4. 微信5.0 Android版飞机大战破解无敌模式手记
  5. 最新整理英文论坛大全(有评论)
  6. zip暴力破解工具Python实现
  7. Linux-nginx配置文件详解与配置与请求行/头/体过长414、413配置
  8. Alpha测试和Beta测试:定义和区别
  9. 辅助工具之Zoomit
  10. 大话设计模式-23中设计模式分类