题解:P16798 [蓝桥杯 2026 国 B] Token 词元

· · 题解

题意

给出 p 数组的要求,让我们推出 c 数组对 a 数组的限制,求出 a 数组总和最小值。

思路

$a_i$ 是正整数,又想要和最小,那就将初值设为 $1$。我们感性的认为,$a_i$ 的最大值不会很大,便可以采用**双向传递**的方法。 ## 做法 1. **从左往右**推,处理递增约束。若 $c_i<c_{i+1}$,则将 $a_{i+1}$ 赋值为 $a_{i+1}$ 和 $a_i+1$ 中的最大值。 2. **从右往左**推,处理递减约束。若 $c_i>c_{i+1}$,则将 $a_i$ 赋值为 $a_i$ 和 $a_{i+1}+1$ 中的最大值。 ## 证明 1. 处理递增或递减约束时,不会破坏其余约束。 2. 在 $c_i=c_{i+1}$ 时,不会无故拉高 $a_i$ 或 $a_{i+1}$ 的值。 3. 取较大值能同时满足两边的约束。 # 代码 ```cpp #include<bits/stdc++.h> using namespace std; #define int long long #define endl '\n' const int N=2e5+5; int p[N],c[N],a[N]; signed main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int n;cin>>n; for(int i=1;i<=n;i++){ cin>>p[i]; a[i]=1;//赋值 } //计算c数组的值 for(int i=1;i<=n;i++){ if(i!=1&&p[i]>p[i-1]) c[i]++; if(i!=n&&p[i]>p[i+1]) c[i]++; } //处理递增约束 for(int i=1;i<n;i++){ if(c[i]<c[i+1]) a[i+1]=max(a[i+1],a[i]+1); } //处理递减约束 for(int i=n-1;i>0;i--){ if(c[i]>c[i+1]) a[i]=max(a[i],a[i+1]+1); } //计算总和 int ans=0; for(int i=1;i<=n;i++){ ans+=a[i]; } cout<<ans<<endl; return 0; } ```