CF1854题解

CF1854A1

这种构造题,我觉得,思路应当是先从特殊情况开始,然后要么转化成特殊情况,要么找性质结合特殊情况构造

或先理解(理解结构)或找基本思路

特殊情况:

全部大于0,前缀和即可 \(n-1\) 次操作

全部小于0,后缀和即可 \(n-1\) 次操作

注意到一般情况,没有什么头绪,太乱了

能不能转化为特殊情况呢

用一个绝对值最大的数,将所有异号的加上这个数,变为同号,次数最多 \(n-1\)

CF1854A2

注意到 \(k<=31\) 数长得很奇怪

考虑到以上的方法跑不满,但若异号的太多会卡出上限

算一下,若异号个数 \(<=12\) 是可行的

若大于呢,可以考虑一下分治,假如说绝对值最大的数为负,那我就把负变为正

这需要我们构造一个更大的正数,发现一个数的上界是 20 考虑到自增是log的,所以将一个数自增大于20就必然成为绝对值最大的数了,次数为5

这种的次数为 7+5=12 可行

CF1854B

大部分都推出来了,最后一步用bitset优化这想破脑袋也想不出

题目限制,想要选择一些数使得选择的 \(a_j\)\(\sum\) 大于当前的 \(i\) 并且使得最终的解锁了的 \(a_i\) 的和减去选择的尽可能要大

从描述就可以发现一个性质,解锁的步数+取得的分数是一个定值,不用全部维护

反悔贪心?

因为发现贪心的过程中不是解锁最小的步数就是最好的

所以有后效性

所以考虑dp,设 \(dp_j\) 表示是否能解锁 \(j\)

主打的是一个可行性dp,因为维护最优性发现有后效性,最优的不代表全局最优

然后就是转移

\(dp_j=dp_j|dp_{j-a_i}\),并且所有 \(j<i\) 的状态都不能用

用bitset维护一下,我不会,现学的

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5;
bitset<N>f;
int n,ans;
int a[N],c[N],s[N];
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        s[i]=a[i]+s[i-1];
    }
    f[1]=1;
    for(int i=1;i<=n;i++){
        f=f|(f<<a[i]);
        c[i]=f[i];
        f[i]=0;
    }
    for(int i=n+1;i<=2*n;i++){
        c[i]=f[i];
        s[i]=s[i-1];
    }
    for(int i=1;i<=2*n;i++){
        if(c[i])  ans=max(ans,s[i]-(i-1));
    }
    printf("%lld",ans);
}

posted @ 2025-09-03 14:28  daydreamer_zcxnb  阅读(7)  评论(0)    收藏  举报