Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)
Codeforces Round #681 (Div. 2, based on VK Cup 2019-2020 - Final)
B
题意:01串,消去连续的1费用为a,将一个0变成1费用为b,问消除所有1的最低费用。
题解:对于每段连续1计算与前一个段的距离len,如果费用len*b<a,选择把一段0变成1,否则直接消去连续的1。
#include<iostream>
using namespace std;
int t,a,b;
string s;
int main(){
cin>>t;
while(t--){
cin>>a>>b;
cin>>s;
int p=0;
for(int i=0;i<s.length();i++){
if(s[i]=='1'){
p=i;
break;
}
}
int ans=0,ok=0,len=1e5+7;
for(int i=p;i<s.length();i++){
if(s[i]=='1'){
if(ok==0){
ans+=min(a,len*b);
ok=1;
len=0;
}
}
if(s[i]=='0'){
ok=0;
len++;
}
}
printf("%d\n",ans);
}
}
C
题意:n个菜,可以自己做,也可以点外卖,自己做要a[i]时间,点外卖b[i]时刻送达,最快最久完成n道菜。(自己做累加时间,点外卖取最长时间)
题解:对于一个某个菜我选择点外卖假如10分钟送达,如果另一个菜点外卖的话9分钟送达,那么我肯定两个菜都点外卖,因为第二个菜不会占用我任何时间,那么我们对外卖的送达时间排序按小到大排序,枚举前i个菜都点外卖的情况,后n-i个菜自己做(用前缀和优化)的时间,更新ans。
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
int t,n;
struct madoka{
ll a;
ll b;
}ma[200007];
ll pre[200007];
bool cmp(madoka a1,madoka a2){
if(a1.a==a2.a){
return a1.b>a2.b;
}
else{
return a1.a<a2.a;
}
}
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>ma[i].a;
}
for(int i=1;i<=n;i++){
cin>>ma[i].b;
}
sort(ma+1,ma+1+n,cmp);
pre[n+1]=0;
for(int i=n;i>=1;i--){
pre[i]=pre[i+1]+ma[i].b;
}
ll ans=1e18+7;
for(int i=0;i<=n;i++){
ans=min(ans,max(ma[i].a,pre[i+1]));
}
printf("%lld\n",ans);
}
}
D
题意:n个数,每次可以选择前或后若干个数都减一,问能否全0;
题解:对于一个递减序列,我当然能完成
如:5 4 3 2 2 >> 4 4 3 2 2 >> 3 3 3 2 2 >> 2 2 2 2 2 >> 0 0 0 0 0 ;
只要把前一个变成于后一个一样,之后再一起减1就好了。(递增同理)
先递减再递增也当然可以,拆开同上操作即可,问题就是,无峰函数怎么判断是否合法,其实也不难,首先先找前第一段递减区间,同上操作,剩下的区间我只需考虑如何尽可能让它递增即可,在区间的值不能增加情况下,让区间尽可能递增,只能让尽可能让每一个位置的前一个位置的值尽可能小。
如:6 5 4 5 4 5 3
找到递减区间 654,
那么省下5 4 5 3,我就让前一个位置值尽可能小,5最多可跟着前面的值减4,到1。
省下 1 4 5 3,前一个位置减了4,但要满足递增,4最多减3,到1,
省下 1 1 5 3,前位置减了3,5可以减3,到2,
省下 1 1 2 3,最后序列递增输出YES,否则NO。
#include<iostream>
using namespace std;
int t,n,a[30007];
int main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int p=n,now=0,ok=1;
for(int i=2;i<=n;i++){
if(a[i]>a[i-1]){
p=i;
now=a[i-1];
a[i]-=now;
break;
}
}
for(int i=p+1;i<=n;i++){
if(a[i]<a[i-1]){
ok=0;
}
else{
int lin=a[i]-a[i-1];
now=min(lin,now);
a[i]-=now;
}
}
if(ok)printf("YES\n");
else{
printf("NO\n");
}
}
}