我们有函数定义:
f ( p ) = ∑ i = 1 n ∣ p i − i ∣ f(p) = \sum_{i=1}^{n} |p_i - i| f(p)=i=1∑n∣pi−i∣
我们需要求出对于所有长度为 n n n 的排列 p p p,函数 f ( p ) f(p) f(p) 可能取到的不同值的个数。
引理:对任意整数 x x x,都有 ∣ x ∣ ≡ x ( m o d 2 ) . |x| \equiv x \pmod 2. ∣x∣≡x(mod2).
因此,
f ( p ) ≡ ∑ i = 1 n ( p i − i ) = ( ∑ i = 1 n p i ) − ( ∑ i = 1 n i ) = ( 1 + 2 + ⋯ + n ) − ( 1 + 2 + ⋯ + n ) = 0 ( m o d 2 ) . f(p)\equiv \sum_{i=1}^n (p_i - i) \;\;=\;\;\Bigl(\sum_{i=1}^n p_i\Bigr)\;-\;\Bigl(\sum_{i=1}^n i\Bigr) \;=\;(1+2+\cdots+n)\;-\;(1+2+\cdots+n) \;=\;0 \pmod 2. f(p)≡i=1∑n(pi−i)=(i=1∑npi)−(i=1∑ni)=(1+2+⋯+n)−(1+2+⋯+n)=0(mod2).
即 f ( p ) f(p) f(p) 一定是偶数。
接下来求 f ( p ) f(p) f(p) 的最值 :
f max = ∑ i = 1 n ∣ ( n − i + 1 ) − i ∣ = ∑ i = 1 n ∣ n + 1 − 2 i ∣ . f_{\max} =\sum_{i=1}^n\bigl|(n-i+1)-i\bigr| =\sum_{i=1}^n\bigl|\,n+1-2i\,\bigr|. fmax=i=1∑n (n−i+1)−i =i=1∑n n+1−2i .
若 n = 2 m n=2m n=2m 为偶数,
f max = 2 ∑ i = 1 m ( 2 m + 1 − 2 i ) = 2 ( ( 2 m − 1 ) + ( 2 m − 3 ) + ⋯ + 1 ) = 2 ⋅ m 2 = n 2 2 . f_{\max} = 2\sum_{i=1}^m (2m+1-2i) =2\bigl((2m-1)+(2m-3)+\cdots+1\bigr) =2\cdot m^2 =\frac{n^2}{2}. fmax=2i=1∑m(2m+1−2i)=2((2m−1)+(2m−3)+⋯+1)=2⋅m2=2n2.
若 n = 2 m + 1 n=2m+1 n=2m+1 为奇数,
f max = 2 ∑ i = 1 m ( 2 m + 2 − 2 i ) = 2 ( ( 2 m ) + ( 2 m − 2 ) + ⋯ + 2 ) = 2 ⋅ m ( m + 1 ) = n 2 − 1 2 . f_{\max} = 2\sum_{i=1}^m (2m+2-2i) =2\bigl((2m)+(2m-2)+\cdots+2\bigr) =2\cdot m(m+1) =\frac{n^2-1}{2}. fmax=2i=1∑m(2m+2−2i)=2((2m)+(2m−2)+⋯+2)=2⋅m(m+1)=2n2−1.
一言以蔽之,可以统一写作
f max = ⌊ n 2 2 ⌋ . f_{\max} \;=\;\Bigl\lfloor \tfrac{n^2}{2}\Bigr\rfloor. fmax=⌊2n2⌋.
猜想 0 ∼ f m a x 0 \sim f_{max} 0∼fmax 的值都可以构造得到,所以 答案 = ⌊ f max 2 ⌋ + 1 \text{答案} = \left\lfloor \frac{f_{\text{max}}}{2} \right\rfloor + 1 答案=⌊2fmax⌋+1 。
有 c c c 个元素负责“还原” x x x 的二进制位,其余 n − c \;n-c\; n−c 个元素都填 “1”。
这 ( n − c ) (n-c) (n−c) 个 1 异或的结果是
1 ⊕ 1 ⊕ ⋯ ⊕ 1 ⏟ n − c 次 = ( n − c ) m o d 2. \underbrace{1\oplus1\oplus\cdots\oplus1}_{n-c\text{ 次}} = (n-c)\bmod2. n−c 次 1⊕1⊕⋯⊕1=(n−c)mod2.
为了让它们的异或等于 0(否则会把最终整体异或从 x x x 变成 x ⊕ 1 x\oplus1 x⊕1),我们要保证 ( n − c ) (n-c) (n−c) 是偶数。
因此如果 ( n − c ) (n-c) (n−c) 是奇数,就再多放一个 “1” ——这样放了 ( n − c + 1 ) (n-c+1) (n−c+1) 个 1,总和增加了 ( n − c + 1 ) (n-c+1) (n−c+1),且异或归为 0。
最终总和
x + ( n − c ) + ( ( n − c ) m o d 2 ) x\;+\;(n-c)\;+\;\bigl((n-c)\bmod2\bigr) x+(n−c)+((n−c)mod2)
1 , … , 1 ⏟ n − 2 , 2 , 3 ⟹ 和 = ( n − 2 ) × 1 + ( 2 + 3 ) = n + 3. \underbrace{1,\dots,1}_{n-2},\,2,\,3 \quad\Longrightarrow\quad \text{和}=(n-2)\times1+(2+3)=n+3. n−2 1,…,1,2,3⟹和=(n−2)×1+(2+3)=n+3.
n n n 偶数:全放 n n n 个 1,异或为 0,总和 = n =n =n。
n n n 奇数:留 n − 3 n-3 n−3 个 1,再加 [ 1 , 2 , 3 ] [1,2,3] [1,2,3](因为 1 ⊕ 2 ⊕ 3 = 0 1\oplus2\oplus3=0 1⊕2⊕3=0),总和
( n − 3 ) × 1 + ( 1 + 2 + 3 ) = n + 3. (n-3)\times1 + (1+2+3) = n+3. (n−3)×1+(1+2+3)=n+3.
将数值相同的点先合并。
然后从大到小处理所有按钮
#include
using namespace std;
using ll = long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--){
int n;
cin >> n;
vector<ll> a(n+2, 0); // 哨兵:a[0]=a[n+1]=0
for (int i = 1; i <= n; i++){
cin >> a[i];
}
// 按权重分桶
unordered_map<ll, vector<int>> pos;
pos.reserve(n*2);
for (int i = 1; i <= n; i++){
pos[a[i]].push_back(i);
}
// 取所有不同权重并降序
vector<ll> ws;
ws.reserve(pos.size());
for (auto &kv : pos) ws.push_back(kv.first);
sort(ws.begin(), ws.end(), greater<ll>());
vector<char> flooded(n+2, 0); // flooded[i]=1 表示 a[i] 已被按下(更大权重已处理)
ll clones = 0;
// 从大到小处理每个权重
for (ll w : ws){
auto &P = pos[w];
sort(P.begin(), P.end());
int m = P.size();
// 将连续下标段划为一块块
int start = 0;
while (start < m){
int end = start;
while (end+1 < m && P[end+1] == P[end]+1)
end++;
// 这一块的下标区间 [L..R]
int L = P[start], R = P[end];
// 看看左右是否有已 flooded 的位置
bool reachable = false;
if (flooded[L-1]) reachable = true;
if (flooded[R+1]) reachable = true;
if (!reachable){
// 必须新建一个 clone
clones++;
}
// 将这一块全部标记为 flooded
for (int k = start; k <= end; k++){
flooded[P[k]] = 1;
}
start = end+1;
}
}
cout << clones << "\n";
}
return 0;
}