题解:P12880 [蓝桥杯 2025 国 C] 数字配对

· · 题解

P12880[蓝桥杯 2025 国 C] 数字配对

给定长度为 n 的序列 a,取出若干数对 a_i,a_j 使得 i<j,~a_j=a_i+1,每一个数至多被取 1 次,求最多取多少对。

:::info[HintA] **性质:** 如果当前最小值 $a_i=a_j=x,a_k=x+1,i<j<k$,则 $(j,k)$ 一定比 $(i,k)$ 更优。 ::: :::info[HintB] **性质:** 如果当前最小值中下标最大的点为 $i$,且 $a_i=x,a_j=a_k=x+1,i<j<k$,则 $(i,k)$ 一定比 $(i,j)$ 更优。 ::: :::info[HintC] 考虑记录每一种数值的出现下标位置,按照数值从小到大贪心,在过程中用**双指针**维护信息。 ::: :::info[sol] **贪心;双指针;对于配对问题考虑从数值角度贪心。** **性质**如果当前最小值 $a_i=a_j=x,a_k=x+1,i<j<k$,则 $(j,k)$ 一定比 $(i,k)$ 更优。 **证明** 显然 $i,j$ 都只能与 $x+1$ 的位置组对。 $(i,k)$ 与 $(j,k)$ 对答案的贡献同为 $1$,但是 $i<j$,所以“能与 $j$ 成对的 $x+1$ 的位置”都能与 $i$ 成对。于是匹配 $(j,k)$,留下 $i$ 一定更优。 证毕。 **性质**如果当前最小值中下标最大的点为 $i$,且 $a_i=x,a_j=a_k=x+1,i<j<k$,则 $(i,k)$ 一定比 $(i,j)$ 更优。 **证明** 显然如果 $j,k$ 与值为 $x$ 的点都能成对,而 $j$ 比 $k$ 更能和值为 $x+2$ 的点成对,于是匹配 $(i,k)$,保留 $j$,一定更优。 证毕。 **做法** 综合上面的性质,算法应该很显然了。 考虑记录每一种数值的出现下标位置,按照数值从小到大贪心。 对于数值 $i+1$ 的下标最大的点(下标设为 $x$),不断找到数值 $i$ 中最后下标一个 $\ge x$ 的位置进行匹配。 **代码** ```cpp const int N=1e6+5; int n,ans; vector<int>v[N]; signed main(){ n=read(); for(int i=1;i<=n;++i){ int x=read(); v[x].push_back(i); } for(int i=1;i<=1e6;++i){ while(v[i+1].size()){ while(v[i].size() and v[i].back()>=v[i+1].back()) v[i].pop_back(); if(!v[i].size())break; ++ans,v[i+1].pop_back(),v[i].pop_back(); } } write(ans); return 0; } ``` :::