CCF 202112-2 序列查询新解(C++)
该题关键点在于:分段计算
- 先对f分段:
for(int i=1;i<=n+1;i++) //以 f(i) 为区域划分计算 在此区域内f的取值相同,值为:i-1。
- 再对每个f值相同的区域按照g值进行分段:
for(int j=a[i-1];j<=a[i]-1;j=j+Long){//此区间内有Long个g取值为g(j)的数
- j 值改变条件为:
j=j+Long
,这个Long为变值,因为g取值相同的区间不完全与 f 取值相同的区间对齐。
所以每次都要计算此Long:Long=NumLong=NumEnd-j+1;
注:由于此特性,所以g取值的上界可能超出了此区间(按f取值相同来划分的区间)的上界
所以需要此语句:if(NumEnd>a[i]-1) NumEnd=a[i]-1;
//上界超出范围,变为区间最上界 ,来将此情况的bug修复。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
#define num 100002
int n = 0;
int N = 0;
int a[num]={0};
int r = 0;
int Long = 0;
long long sum = 0;
void input()
{ // 输入
cin >> n >> N;
for (int i = 1; i <= n; i++){
cin >> a[i];
}
}
long long g(int x)
{ // 计算g(x)的值
return x/r;
}
int main()
{
input();
r=N/(n+1);
a[n+1]=N;
a[0]=0;
// Long = r;
for(int i = 1; i <= n+1; i++){//以f(i)为区域划分计算
long long sum1 = 0;//记录此小区间差值的和
for (int j = a[i-1]; j <= a[i]-1; j = j+Long){
int NumEnd=(g(j)+1)*r-1;
if (NumEnd>a[i]-1) NumEnd=a[i]-1;
int NumLong = NumEnd-j+1;
long long f_g = abs(i-1-g(j));
sum1 = sum1+f_g*NumLong;
Long = NumLong;
}
sum += sum1;
}
cout << sum << endl;
return 0;
}