牛客练习赛74
省流:唐了但没完全唐。
A
简单DP。用第二维状态0表示没拿的多一,1表示拿和没拿的相等,2表示拿了的多一。
挂了一发的原因是起始状态忘记初始化了。
int n,a[100005];
long long f[100005][3];//状态0表示没拿多一,1表示拿和没拿相等,2表示拿了的多一
int main(){
R(n);
for(int i=1;i<=n;i++){
R(a[i]);
}
f[0][1]=0; //初始时拿和没拿相等
f[0][0]=f[0][2]=-1e18; //唐:忘记初始化了
for(int i=1;i<=n;i++){
f[i][1]=max(f[i-1][0]+a[i],f[i-1][2]);
f[i][0]=f[i-1][1];
f[i][2]=f[i-1][1]+a[i];
}
cout<<max(max(f[n][0],f[n][1]),f[n][2])<<endl;
return 0;
}
B
贪心,将每个手斧的破坏程度从小到大排序,分别在树高的集合中二分,与能砍的树中树高最大的匹配。
int n,m,a[100005],b[100005];
multiset<int> s;
int main(){
R(n);R(m);
for(int i=1;i<=n;i++){
R(a[i]);
s.insert(a[i]);
}
for(int i=1;i<=m;i++)
R(b[i]);
sort(b+1,b+1+m);
int cnt=0;
for(int i=1;i<=m;i++){
if(s.empty()) break;
auto p=s.upper_bound(b[i]);
if(p!=s.begin()){
s.erase(--p);
cnt++;
}
}
cout<<cnt<<endl;
return 0;
}
C
分类讨论题。详情见代码。
int T;
long long a1,b1,a2,b2;
int main(){
R(T);
while(T--){
R(a1);R(b1);R(a2);R(b2);
long long ans=max(a1+b1,a2+b2);
//A 写数学 B 写语文
ans=min(ans,max(a1+b1,max(a1,b2)+a2/2)); //B抄A不抄
ans=min(ans,max(max(a1,b2)+b1/2,max(a1,b2)+a2/2)); //都抄
ans=min(ans,max(max(a1,b2)+b1/2,b2+a2)); //A抄B不抄
//B 写数学 A 写语文
ans=min(ans,max(a1+b1,max(b1,a2)+b2/2)); //B抄A不抄
ans=min(ans,max(max(a2,b1)+a1/2,max(b1,a2)+b2/2)); //都抄
ans=min(ans,max(max(b1,a2)+a1/2,b2+a2)); //A抄B不抄
//唐:忘记可以一个人写两份作业了给另一个人抄了。
//A 写数学语文
ans=min(ans,max(a1+b1,a1+max(b1,a2/2)+b2/2));
ans=min(ans,max(a1+b1,b1+max(a1,b2/2)+a2/2));
//B 写数学语文
ans=min(ans,max(a2+b2,a2+max(b2,a1/2)+b1/2));
ans=min(ans,max(a2+b2,b2+max(a2,b1/2)+a1/2));
printf("%lld\n",ans);
}
return 0;
}
D
数据结构题(大概)
一个想法是把每次操作3扣除的血量累加起来考虑,就可以实现对整体血量进行一个计算。
假设扣除的总血量为$dlt$,那么我们维护的血量为$hp_i=realhp_i+dlt$。具体表现为编号$x$加入战斗时血量设为$b_x+dlt$,撤出战斗时血量设为0(或者负数),为编号$x$恢复血量$h$时血量等于$\min\{hp_x+h,b_x+dlt\}$
。
以上操作1,2,4可以用一个数组维护血量。
对于操作3,我们注意到每个人死亡后不会再参与战斗,那么我们可以同时用一个set去维护血量,每次操作3时暴力从小到大判断set中各元素血量是否小于$dlt$进而进行删除。这样对于操作3,每个元素最多被遍历一次。
操作1,2,4在维护数组时同时维护set即可。
总复杂度$O((n+k) \log_2 n)$
int n,k;
long long m;
int a[100005],b[100005];
typedef pair<ll,int> P;
set<P> hp;
long long hp2[100005];
int main(){
R(n);R(m);R(k);
long long atk=0;
for(int i=1;i<=n;i++){
R(a[i]);
atk+=a[i];
}
for(int i=1;i<=n;i++){
R(b[i]);
hp.insert(P(b[i],i));
hp2[i]=b[i];
}
ll dlt=0;
int excnt=0;
while(k--){
int opt,x,h;
R(opt);R(x);
if(opt==1){
hp.insert(P(b[x]+dlt,x));
hp2[x]=b[x]+dlt;
atk+=a[x];
excnt--;
}
else if(opt==2){
hp.erase(P(hp2[x],x));
hp2[x]=0;
atk-=a[x];
excnt++;
}
else if(opt==3){
dlt+=x;
for(auto i=hp.begin();i!=hp.end()&&i->first<=dlt;i=hp.begin()){
atk-=a[i->second];
hp2[i->second]=0;
hp.erase(i);
}
}
else{
R(h);
if(hp2[x]>0){
hp.erase(P(hp2[x],x));
hp2[x]=min(hp2[x]+h,b[x]+dlt);
hp.insert(P(hp2[x],x));
}
}
if(hp.size()+excnt<=0){
puts("NO");
return 0;
}
m-=atk;
if(m<=0){
puts("YES");
printf("%llu\n",hp.size()+excnt);
return 0;
}
}
puts("NO");
return 0;
}
其余咕。