A - Setting up Camp

水题,好像之前在新生赛写过类似的,小小写个特判即可

void solve(){
    CIN(a);CIN(b);CIN(c);
    if((b%3)!=0&&3-(b%3)>c){cout<<-1<<ET;return;}
    cout<<a+(b+c)/3+((b+c)%3!=0)<<ET;
}

B - Fireworks

虽然不知道为什么,但是这样写能过

void solve(){
    CIN(a);CIN(b);CIN(m);m++;
    cout<<(m/a+(m%a!=0))+(m/b+(m%b!=0))<<ET;
}

隔壁kk的解法(想必是秒了的):

void solve(){
    CIN(a);CIN(b);CIN(m);
    cout<<(a+m)/a+(b+m)/b<<ET;
}

C - Left and Right Houses

直接上O(n)暴力即可

void solve(){
    CIN(n);string s;cin>>s;
    vector<int> pre,suf;pre.push_back(0);
    FOR(i,1,n)pre.push_back(pre[i-1]+(s[i-1]=='0'));
    reverse(s.begin(),s.end());suf.push_back(0);
    FOR(i,1,n)suf.push_back(suf[i-1]+(s[i-1]=='1'));suf.push_back(0);
    reverse(suf.begin(),suf.end());suf.push_back(0);//一坨预处理,其实完全可以只用一个pre解决
    ll ans=n;
    rFOR(i,n,0){
        if(pre[i]>=ceil(1.0*i/2)&&suf[i+1]>=ceil(1.0*(n-i)/2){
            if(abs(i-1.0*n/2)<=abs(ans-1.0*n/2))ans=i;
        }
    }
    cout<<ans<<ET;
}

D - Seraphim the Owl

第m个人后面的写贪心统计,前面的m个人也写暴力统计最小结束支出

void solve(){
    CIN(n);CIN(m);
    vector<ll> a,b;a.push_back(0);b.push_back(0);
    FOR(i,1,n){CIN(tmp);a.push_back(tmp);}
    FOR(i,1,n){CIN(tmp);b.push_back(tmp);}

    vector<ll> suf(m+2,0);//前m个人倒序统计前缀和
    rFOR(i,m,2)suf[i]=suf[i+1]+b[i];

    ll ans=0;//后面的人贪心收集答案
    rFOR(i,n,m+1)ans+=min(a[i],b[i]);

    ll cost=a[m];
    rFOR(i,m,2){//查询前m个人的最小支出
        if(cost>suf[i]+a[i-1]){
            cost=suf[i]+a[i-1];
        }
    }

    cout<<ans+cost<<ET;
}

E - Binary Search

直接模拟,最后收敛到的数与目标数交换即可。

  • 假如目标数不在二分路径上,那么交换后最终收敛肯定能到目标数上
  • 假如目标数在路径上,那么由题目二分定义知道,处在l下标的数必然满足 $p_l\le x$,而 $l$ 是二分遍历的左端点,因此交换并不会改变二分路径。
void solve(){
    CIN(n);CIN(x);
    vector<ll> a(n+1);
    int index=0;
    FOR(i,1,n){cin>>a[i];if(a[i]==x)index=i;}

    int l=1,r=n+1;
    while(r-l!=1){
        int m=(r+l)/2;
        if(a[m]<=x)l=m;
        else r=m;
    }
    cout<<1<<ET;
    cout<<l<<" "<<index<<ET;
}

F - Kirill and Mushrooms

用一个大顶堆存没采的蘑菇,小顶堆存采了的蘑菇,然后模拟一下,一边取最大的,一边从两个堆里删除权值降为0的蘑菇,再判断答案即可。

void solve(){
    CIN(n);
    vector<ll> a(n+3),p(n+3);
    FOR(i,1,n)cin>>a[i];
    FOR(i,1,n)cin>>p[i];
    
    multiset<ll,greater<ll>>no;
    multiset<ll,less<ll>>get;
    FOR(i,1,n)no.insert(a[i]);
    ll k=1;
    pair<ll,int> ans={0,0};
    while(!no.empty()){
        if(k>=2){
            ll x=a[p[k-1]];
            if(no.find(x)!=no.end())no.erase(no.find(x));
            else get.erase(get.find(x));
        }
        if(k+k-1>n)break;
        while(get.size()<k){
            get.insert(*no.begin());
            no.erase(no.begin());
        }
        ll pro=k*(*get.begin());
        if(ans.first==pro)ans.second=min(ans.second,k);
        else if(ans.first<pro)ans={pro,k};
        k++;
    }
    cout<<ans.first<<" "<<ans.second<<ET;
}

附录

这里贴上用到的头部文件和main函数:

#include<iostream>
#include<vector>
#include<cmath>
#include<bits\stdc++.h>
#define ll long long
#define ld long double
using namespace std;
#define ET '\n'
#define FOR(i,a,b) for(ll i=(a);i<=(b);i++)
#define rFOR(i,a,b) for(ll i=(a);i>=(b);i--)
//双向for循环
#define rep(i,a,b) for(ll i=(a);i!=(b)+2*(a<b)-1;i+=2*(a<b)-1)
#define CIN(a) ll a;cin>>a
#define DCIN(a) ld a;cin>>a
#define CA cout<<ans<<ET
#define CY cout<<"YES"<<ET
#define CN cout<<"NO"<<ET
#define max(a,b) ((a>b)?(a):(b))
#define min(a,b) ((a<b)?(a):(b))
//没有C++20就不能用ranges了
//#define PP(l,r,CK) *ranges::partition_point(ranges::iota_view((l),(r)+1),(CK))
string ANS[2]={"No\n","Yes\n"};

void solve(){

}

int main(){
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    //pre();
    CIN(t);while(t--)
    solve();
    return 0;
}