题目
思路
第一个思路就是按照表层题意:
- 遍历
x
∈
[
0
,
m
)
x \in [0, m)
x∈[0,m) ,对于每个
x
x
x,求对应的
a
[
i
]
a[i]
a[i]
采用二分搜索
- 得到 f ( x ) = i f(x) = i f(x)=i,转而求 g ( x ) g(x) g(x)
复杂度:
O
(
m
⋅
l
o
g
n
)
O(m \cdot logn)
O(m⋅logn) 不可行
第二个思路是分区间处理:
- 先按照 f ( x ) f(x) f(x) 的不同取值分不同区间
- 再按照
g
(
x
)
g(x)
g(x) 的不同取值细分区间
2.1. g ( x ) g(x) g(x)的取值在一般情况下,在一段长为 r r r 的区间上是一致的
2.2. 但是有可能这个区间会被 1. 1. 1. 中分出的区间给截断例如 a[i] 不是 r 的整数倍 || a[i+1] 不是 r 的整数倍
最终分出的区间应该是:
\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;
[
j
,
m
i
n
(
j
r
×
r
+
r
−
1
,
a
[
i
+
1
]
−
1
)
]
,
j
∈
[
a
[
i
]
,
a
[
i
+
1
]
)
,
i
∈
[
0
,
n
]
[\;j,\;min(\frac{j}{r}\times r+r-1, \;a[i+1]-1)\; ],\; j \in [\;a[i],\;a[i+1]\;),i \in [0,n]
[j,min(rj×r+r−1,a[i+1]−1)],j∈[a[i],a[i+1]),i∈[0,n]
这个复杂度不会分析哈哈
可行
错误代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int a[N];
int main()
{
int n, m;
cin >> n >> m;
int r = m / (n+1);
for(int i = 1; i <= n; i++) cin >> a[i];
int error = 0;
for(int i = 0; i < m; i++)
{
int gx = i / r;
int l = 0, r = i;
while(l < r)
{
int mid = (l + r + 1) >> 1;
if(a[mid] <= i && mid <= n) l = mid;
else r = mid-1;
}
int fx = l;
error += abs(fx - gx);
}
cout << error;
return 0;
}
正确代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
int a[N];
int n, m;
LL e;
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++) cin >> a[i];
int r = m / (n+1);
a[n+1] = m;;
for(int i = 0; i <= n; i++)
{
int f = i; int d = 0;
for(int j = a[i]; j < a[i+1]; j += d)
{
int g = j / r;
int last = a[i+1]-1;
last = min(last, g*r+r-1);
d = last - j + 1;
e += 1LL * d * abs(f - g);
}
}
cout << e;
return 0;
}