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);
}

浙公网安备 33010602011771号