返回顶部

Codeforces Round #643 (Div. 2)【ABCDE】(题解)

涵盖知识点:差分、三分

比赛链接:传送门

A - Sequence with Digits

题意: 构造数组,下一个元素的值为上一个元素的值加上其各位数字中最小值和最大值的积。给定第一个元素,求第\(k\)个元素的值。
题解: 当出现某个数字的某一位为0时这个数字就永远不变。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int t;cin>>t;
    while(t--){
        ll a,k;
        cin>>a>>k;
        ll ans=a;
        k--;
        while(k--) {
            ll tmp=ans;
            int mn=10,mx=-1;
            while(tmp){
                int p=tmp%10;
                tmp/=10;
                mx=max(p,mx);
                mn=min(p,mn);
            }
            if(mn==0)break;
            ans+=1ll*mn*mx;
        }
        cout<<ans<<"\n";
    }
    return 0;
}

B - Young Explorers

题意: 经验值为\(e\)的人只能安排在人数大于等于\(e\)的小队中。问最多可以安排几个小队(不必所有人都加入小队)
题解: 排序,计数,贪心。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int t;cin>>t;
    while(t--){
        int n;
        cin>>n;
        vector<int> e(n);
        for(int i=0;i<n;i++)cin>>e[i];
        sort(e.begin(),e.end());
        int ans=0,cnt=0;
        for(int i=0;i<n;i++){
            if(++cnt==e[i])ans++,cnt=0;
        }
        cout<<ans<<"\n";
    }
    return 0;
}

C - Count Triangles

题意: 求有多少组\((x,y,z)\)满足\(A \leq x \leq B \leq y \leq C \leq z \leq D\)且能组成三角形。
题解: 对于每一个\(x\),我们利用差分对区间\([x+b,x+c]\)进行加一的操作,再做一次前缀和,我们得到的是\(x+y\)的值对应的\((x,y)\)组数。然后对于区间\([c,d]\)内的每一个\(z\)判断有多少组\((x,y)\)满足\(x+y>z\)
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
ll pre[maxn];
int main(){
    int a,b,c,d;
    cin>>a>>b>>c>>d;
    for(int i=a;i<=b;i++){
        pre[i+b]++;
        pre[i+c+1]--;
    }
    for(int i=1;i<maxn;i++)pre[i]+=pre[i-1];
    for(int i=1;i<maxn;i++)pre[i]+=pre[i-1];
    ll ans=0;
    for(int i=c;i<=d;i++)ans+=pre[maxn-1]-pre[i];
    cout<<ans<<"\n";
    return 0;
}

D - Game With Array

题意: 构造长度为\(n\)的数列满足和为\(s\)且存在一个\(k\),使得不存在某个子序列的和为\(k\)\(s-k\)
题解: 如果\(s\ge 2n\),那么可以构造序列\(2,2,2,\ldots,s-2(n-1)\),取\(k=1\)。否则无解。具体证明官方题解其实是我看不懂
证明:(队友给的) 另有一种构造方法\(1,1,1,1,\ldots,s-n+1\)。所能够取到的值为\([1,n-1]\bigcup[s-n+1,s]\)。如果\(s-n+1\le n-1+1\)\(s\le 2n-1\)就会无解。扩展的,如果我们改变前\(n-1\)个数的任何一个数,就只是影响两个区间的范围,并不影响最终的结论。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+10;
int main(){
    int n,s;
    cin>>n>>s;
    if(2*n<=s){
        puts("YES");
        for(int i=0;i<n-1;i++)cout<<2<<" ";
        cout<<s-2*(n-1)<<"\n"<<1<<"\n";
    }
    else puts("NO");
    return 0;
}

E - Restorer Distance

题意: 高度+1、-1、其中一个+1另一个-1分别花费\(a,r,m\),现在给定初始高度,问最少花费多少使得所有位置的高度都一样高。(没有额外的辅助位置)
题解: 大概脑补一下花费应该是有简单的单调性的(先递减再递增)证明不会。三分高度求极值点然后求极值就过了。。
Accept Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
int h[maxn];
int n,a,r,m;
ll check(int mid){
    ll res=0,add=0,sub=0;
    for(int i=1;i<=n;i++){
        if(h[i]<mid)add+=mid-h[i];
        else sub+=h[i]-mid;
    }
    res=add*a+sub*r;
    if(a+r>m)res+=m*min(add,sub)-min(add,sub)*(a+r);
    return res;
}
int main(){
    cin>>n>>a>>r>>m;
    for(int i=1;i<=n;i++)cin>>h[i];
    int lb=0,rb=1e9;
    while(lb<rb){
        int ml=lb+(rb-lb)/3,mr=rb-(rb-lb)/3;
        ll resl=check(ml),resr=check(mr);
        if(resl>resr)lb=ml+1;
        else rb=mr-1;
    }
    cout<<check(lb)<<"\n";
    return 0;
}
posted @ 2020-05-17 14:09  Charles1999  阅读(253)  评论(0编辑  收藏  举报