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

P5771 [JSOI2016] 反质数序列

posted @ 2026-07-14 14:57  凉茶映屏红  阅读(12)  评论(0)    收藏  举报