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