20260714考试总结
P3518 [POI 2011] SEJ-Strongbox
P4095 [HEOI2013] Eden 的新背包问题
首先是没有删除的情况,也就是一个普通的二进制拆分多重背包。那么我们接下来考虑带有删除的情况,现在删除了 \(x\) 则我们可以将答案拆分成两个部分,第一个是由 \(1\) 至 \(x-1\) 的,第二个是由 \(x+1\) 至 \(n\) 的,这两个中每个分别占据一些容量。因此我们分别从前后两边跑01背包,求答案就枚举两个01背包分别占据的容量即可。
P4343 [SHOI2015] 自动刷题机
阅读题意后发现答案是具有单调性的,即 \(n\) 越小,切掉的题目就会越多。因此我们考虑二分答案。
赛时代码:
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=100005,inf=1e18;
int n,k;
int a[N];
bool check1(int x){
int cnt=0,sum=0;
for(int i=1;i<=n;i++){
sum=max(0ll,sum+a[i]);
if(sum>=x){
cnt++;
sum=0;
}
}
return cnt<=k;
}
bool check2(int x){
int cnt=0,sum=0;
for(int i=1;i<=n;i++){
sum=max(0ll,sum+a[i]);
if(sum>=x){
cnt++;
sum=0;
}
}
return cnt>=k;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
// freopen("machine.in","r",stdin);
// freopen("machine.out","w",stdout);
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
if(k>n){
cout<<-1;
return 0;
}
int l=-2,r=inf;
while(l+1<r){
int mid=(l+r)/2;
if(check1(mid))r=mid;
else l=mid;
}
if(r==-1){
cout<<-1;
return 0;
}
cout<<r<<' ';
l=-1,r=inf+1;
while(l+1<r){
int mid=(l+r)/2;
if(check2(mid))l=mid;
else r=mid;
}
cout<<l;
return 0;
}
错误原因,我的判断只是 \(\le\) 和 \(\ge\),所以不一定是等于的情况,所以在判断答案时需要判断 \(check(l)\) 与 \(check(r)\) 与 \(k\) 相等。
就像这样:
if(check(r)!=k){
cout<<-1;
return 0;
}

浙公网安备 33010602011771号