题解:CF1355B Young Explorers

题解:CF1355B Young Explorers

1.思路

最优化问题,考虑 dp。

2.状态转移

fif_i 为序列前 i 项能分多少组。 如果不单独为一组,那么 fi=fi1f_i=f_{i-1}

  • 如果不单独一组,那么 aia_i 就成了该子序列的最大值,为了保证能更多地分,那么该子序列长度至少为 aia_i

  • 如果要分,分完以后,剩下 iaii-a_i 个数,组数加 1。

i<aii<a_i 时也就是不够分时,考虑第一种情况,直接不管。

iaii \ge a_i 时,可以单独分一组,那么考虑第二种情况,能多分就多分。

得到状态转移方程:

fi={fi1 i<aimax(fi1,fiai+1) iaif_i = \begin{cases} f_{i-1} \hspace{3cm}\ i<a_i\\ \max(f_{i-1}, f_{i-a_i}+1) \hspace{0.6cm}\ i\ge a_i \\ \end{cases}

code:

#include<bits/stdc++.h>
using namespace std;
int t, n, a[200005], f[200005];
int main(){
    scanf("%d", &t);
    while(t --){
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
        sort(a + 1, a + n + 1);//排序使得a[i]为子序列最大值
        for(int i = 1; i <= n; i ++){
            f[i] = f[i - 1];//先赋为上一个值
            if(i >= a[i]) f[i] = max(f[i - 1], f[i - a[i]] + 1);//如果可以添加进子序列,取最大值
        }
        printf("%d\n", f[n]);
        for(int i = 1; i <= n; i ++) f[i] = 0;//手动清空用memset会超时
    }
}

posted on 2024-04-06 13:17  zhangzirui66  阅读(10)  评论(0)    收藏  举报  来源

导航