Codeforces Round 980 (Div2,A-D)

A - Profitable Interest Rate

1
2
3
4
5
6
7
8
9
10
11
12
13
void solve(){
int a,b;cin>>a>>b;
if(a>=b){
cout<<a<<"\n";
}else{
int k=2*a-b;
if(k>0){
cout<<k<<"\n";
}else{
cout<<0<<"\n";
}
}
}

B - Buying Lemonade

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void solve(){
int n,k;cin>>n>>k;
vector<int>a(n);
for(int i=0;i<n;i++) cin>>a[i];
sort(a.begin(),a.end());
int sum=0,ans=0,mn=0;
for(int i=0;i<n;i++){
a[i]-=mn;
if(sum+a[i]*(n-i)<k){
sum+=a[i]*(n-i);
mn+=a[i];ans+=a[i]*(n-i);
}else{
ans+=k-sum;
break;
}
ans++;
}
cout<<ans<<"\n";
}

C - Concatenation of Arrays

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void solve(){
int n;cin>>n;
vector<array<int,3>>a(n);
for(int i=0;i<n;i++){
cin>>a[i][0]>>a[i][1];
a[i][2]=a[i][0]+a[i][1];
}
sort(a.begin(),a.end(),[&](auto l,auto r){
if(l[2]!=r[2])return l[2]<r[2];
else return min(l[0],l[1])<min(r[0],r[1]);
});
for(int i=0;i<n;i++){
cout<<a[i][0]<<" "<<a[i][1]<<" ";
}
cout<<"\n";
}

D - Skipping

只有答题才能得分,所以跳题相当于花费a[i]从位置i转移到b[i]

答题就是花费0从i转移到i-1

最终答案就是所有能遍历到的位置上的a[i]-cost[i]

b[i]小于等于i时选择跳过是不明智的,因为此时在到达b[i]的过程中通过答题到b[i]能获得的分数一定更大

i 到 j 有两种方法,第一种是 j=b[i],直接从 i 跳到 j ;第二种是 i<j<b[i] ,从 i 跳到 b[i] 再向左答题到 j,两种方法的花费都是a[i],

所以我们遍历所有位置,每次取能到当前位置且花费最小,转移到当前位置求每个能遍历到的位置的最小花费

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void solve(){
int n;cin>>n;
vector<pair<int,int>>a(n+1);
for(int i=1;i<=n;i++) cin>>a[i].first;
for(int i=1;i<=n;i++) cin>>a[i].second;
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>pq;
pq.push({a[1].first,a[1].second});
vector<int>dp(n+1,1e18);
dp[1]=0;
for(int i=2;i<=n;i++){
while(pq.size()&&pq.top().second<i){
pq.pop();
}
if(pq.empty()){
break;
}
dp[i]=pq.top().first;
if(a[i].second>i){
pq.push({dp[i]+a[i].first,a[i].second});
}
}
int sum=0,ans=0;
for(int i=1;i<=n;i++){
sum+=a[i].first;
ans=max(ans,sum-dp[i]);
}
cout<<ans<<"\n";
}

Welcome to my other publishing channels