zoukankan      html  css  js  c++  java
  • Codeforces Round #642 (Div. 3)【ABCDEF】(题解)

    涵盖知识点:思维、dp

    比赛链接:传送门

    A - Most Unstable Array

    题意: 要求构造长度为(n)的非负数组使得和为(m)(sumlimits_{i=1}^{n-1} |a_i - a_{i+1}|)最大化
    题解: (0,m,0,0,0,0ldots)。特判(1,2)
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int t;cin>>t;
        while(t--) {
            int n, m;
            cin >> n >> m;
            if (n >= 3)cout << 2 * m << "
    ";
            else cout << m * (n - 1) << "
    ";
        }
        return 0;
    }
    

    B - Two Arrays And Swaps

    题意: 至多(k)次机会可以互换数组(a,b)的任何一个数。求(a)的最大和。
    题解: (a)最小的换(b)最大的,直到(a)全部比(b)大。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=110;
    int a[maxn],b[maxn];
    int main(){
        int t;cin>>t;
        while(t--) {
            int n,k;
            cin>>n>>k;
            int sum=0;
            for(int i=0;i<n;i++)cin>>a[i],sum+=a[i];
            for(int i=0;i<n;i++)cin>>b[i];
            sort(a,a+n);
            sort(b,b+n);
            reverse(b,b+n);
            for(int i=0;i<k;i++){
                if(a[i]>=b[i])break;
                sum+=b[i]-a[i];
            }
            cout<<sum<<"
    ";
        }
        return 0;
    }
    

    C - Board Moves

    题意: (n imes n)的方格依次标号((n)是奇数)。每次操作可以将一个方格中的一个数移动到与其相邻的方格(包括斜对角)。求最少几次操作使得某个方格含有全部数字。
    题解: 全移到中间。每一圈距离中心的距离相等。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=110;
    typedef long long ll;
    int main(){
        int t;cin>>t;
        while(t--) {
            int n;
            cin>>n;
            ll ans=0;
            for(int i=1;i<=n/2;i++)ans+=1ll*i*i*8;
            cout<<ans<<"
    ";
        }
        return 0;
    }
    

    D - Constructing the Array

    题意: 给定初始全0数组。现在对于每次操作,要求找到最长的全0子串(相等长度选左边那个)。将其中间(偶数偏左)的数赋值为当前操作的次数。
    题解: 优先队列维护。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
    int ans[maxn];
    struct Node{
        int l,r;
        bool operator <(const Node &b)const{
            return b.r-b.l!=r-l?l-r>b.l-b.r:l>b.l;
        }
        Node()=default;
        Node(int _l,int _r){l=_l,r=_r;}
    };
    priority_queue<Node> q;
    int main(){
        int t;cin>>t;
        while(t--) {
            memset(ans,0,sizeof ans);
            int n;
            cin>>n;
            q.push(Node{1,n});
            int cnt=0;
            while(!q.empty()){
                Node tmp=q.top();
                q.pop();
                int mid=(tmp.l+tmp.r)/2;
                ans[mid]=++cnt;
                if(tmp.l<mid)q.push(Node(tmp.l,mid-1));
                if(tmp.r>mid)q.push(Node(mid+1,tmp.r));
            }
            for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
            cout<<"
    ";
        }
        return 0;
    }
    

    E - K-periodic Garland

    题意: 给定(01)串,每次操作可以使(0)变为(1)或者(1)变成(0)。求最少几次操作使得所有的相邻(1)的间隔为(k)
    题解: 首先我们计算出原串中的(1)的个数为(cnt)。然后枚举(mod k)意义下的每一位为(1)的情况所需个数。注意如果一开始或某个位置需要从(0)变为(1)的次数大于之前原本是(1)的个数,我们可以认为前面的序列全(0)。这样次数更小一些。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    int main() {
        int t;
        cin >> t;
        while (t--) {
            int n, k;
            cin >> n >> k;
            string s;
            cin >> s;
            int cnt=count(s.begin(),s.end(),'1');
            ll ans = 1e18;
            for (int mod = 0; mod < k; mod++) {
                ll here = cnt;
                ll delta = 0;
                for (int i = mod; i < n; i += k) {
                    if (s[i] == '0') delta++;
                    else delta--;
                    delta = min(delta, 0ll);
                    ans = min(ans, here + delta);
                }
            }
            cout << ans << '
    ';
        }
    }
    

    F - Decreasing Heights

    题意: (n imes m)的地图每个位置都有一个值,每次只能向下或者向右走,且对应的方格的值必须为当前方格的值加(1).现在每次操作可以使得一个方格的值减(1)。问最少几次操作可以使得从((1,1))走到((n,n))
    题解: 通过枚举每一个位置的现有值,我们可以确定当前地图所有合法路径应该存在的值。再dp一下就行了。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    int n,m;
    ll a[110][110],dp[110][110];
    ll calc(ll st){
        for(int i=0;i<=n;i++){
            for(int j=0;j<=m;j++)
                dp[i][j]=1e18;
        }
        if (a[1][1]>=st) dp[1][1]=a[1][1]-st;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if ((i==1) && (j==1)) continue;
                if (a[i][j]>=(st+i+j-2)){
                    ll now=a[i][j]-(st+i+j-2);
                    dp[i][j]=min(dp[i-1][j],dp[i][j-1])+now;
                }
            }
        }
        return dp[n][m];
    }
    
    int main(){
        int t;cin>>t;
        while (t--){
            cin>>n>>m;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++)
                    cin>>a[i][j];
            }
            ll ans=1e18;
            for(int i=1;i<=n;i++){
                for(int j=1;j<=m;j++)
                    ans=min(calc(a[i][j]-(i+j-2)),ans);
            }
            cout<<ans<<"
    ";
        }
        return 0;
    }
    
    
  • 相关阅读:
    Netty之WebSocket和四种IO介绍
    java递归展示树形图代码实现以及遇到的问题
    String、String Buffer、String Builder
    物联网的开发应该是什么样子?
    最新 去掉 Chrome 新标签页的8个缩略图
    复化梯形求积分——用Python进行数值计算
    每日设置Bing首页图片为壁纸
    分段二次插值——用Python进行数值计算
    埃尔米特插值问题——用Python进行数值计算
    牛顿插值法——用Python进行数值计算
  • 原文地址:https://www.cnblogs.com/charles1999/p/12896341.html
Copyright © 2011-2022 走看看