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


    目录

    涵盖知识点:思维、贪心、区间dp。

    比赛链接:传送门

    A - Ichihime and Triangle

    题意: 找出数对((x,y,z))满足(ale xle ble yle cle zle d)且能够组成三角形
    题解: ((b,c,c))
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int a,b,c,d;
            cin>>a>>b>>c>>d;
            cout<<b<<" "<<c<<" "<<c<<"
    ";
        }
        return 0;
    }
    

    B - Kana and Dragon Quest game

    题意: 给定原始数字(h),第一种操作可以使(h=leftlfloor frac{h}{2} ight floor + 10);第二种操作可以使(h=h-10)。现在问你能否在(n)次操作一和(m)次操作二之后使得(h<=0)。(可以不用完)
    题解: 先通过操作一到最接近20的数,然后减去(10m)判断正负。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int x,n,m;
            cin>>x>>n>>m;
            while(x>20&&n){
                x=x/2+10;
                n--;
            }
            x-=m*10;
            puts(x>0?"NO":"YES");
        }
        return 0;
    }
    

    C - Linova and Kingdom

    题意: (n)节点的树染黑白两色,其中(k)个是白色。现在要求最大化所有的白点到根节点所经过的黑点总和。
    题解: 贪心。考虑到存在父节点仍为白色节点,所以贪心条件为深度-子节点个数。因为每个子节点在计算的过程中都会减去父节点这一个白色节点的数量。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    typedef long long ll;
    typedef pair<int,int> pii;
    vector<int> edg[maxn];
    int dep[maxn],siz[maxn];
    vector<int> vec;
    void dfs(int u,int pre){
        for(auto v:edg[u]){
            if(v==pre)continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
            siz[u]+=siz[v];
        }
        vec.push_back(dep[u]-siz[u]);
        siz[u]++;
    }
    int main(){
        int n,k;
        cin>>n>>k;
        for(int i=1,u,v;i<n;i++){
            cin>>u>>v;
            edg[u].push_back(v);
            edg[v].push_back(u);
        }
        dfs(1,0);
        sort(vec.begin(),vec.end(),greater<int>());
        ll ans=0;
        for(int i=0;i<k;i++)ans+=vec[i];
        cout<<ans<<"
    ";
        return 0;
    }
    

    D - Xenia and Colorful Gems

    题意: 在三种颜色的数字池中分别取(x,y,z),最小化((x-y)^2+(y-z)^2+(z-x)^2)
    题解: 在确定一个池中的数字之后,二分找到另两个池中最接近的数字。三个池依次扫描一遍就行了。
    Accept Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    inline ll calc(ll x,ll y,ll z){return (x - y) * (x - y) + (y - z) * (y - z) + (z - x) * (z - x);}
    int n[3],v[3][maxn];
    int main(){
        int t;
        cin>>t;
        while(t--){
            cin>>n[0]>>n[1]>>n[2];
            for(int i=0;i<3;i++){
                for(int j=0;j<n[i];j++){
                    cin>>v[i][j];
                }
                sort(v[i],v[i]+n[i]);
            }
            ll ans=6e18+10;
            for(int p1=0;p1<3;p1++){
                for(int p2=0;p2<3;p2++){
                    for(int p3=0;p3<3;p3++){
                        if(p1==p2||p2==p3||p3==p1)continue;
                        for(int i=0;i<n[p1];i++){
                            int pos1=lower_bound(v[p2],v[p2]+n[p2],v[p1][i])-v[p2];
                            int pos2=upper_bound(v[p3],v[p3]+n[p3],v[p1][i])-v[p3];
                            if(pos1!=n[p2]&&pos2!=0){
                                ans=min(ans,calc(v[p1][i],v[p2][pos1],v[p3][pos2-1]));
                            }
                        }
                    }
                }
            }
            cout<<ans<<"
    ";
        }
        return 0;
    }
    

    E - Kaavi and Magic Spell

    题意: 给定串(S,T),长度分别为(n,m),和一个空串(A),每次把S的第一个字母删除然后加到A的前面或者后面。问所有的操作的过程中使得A的前缀为(T)的情况有多少种。
    题解: 区间dp。(dp_{i,j})描述当前和(T)在区间([i,j])的匹配个数。这里将(T)长度扩展为(n),但是从(m)之后的顺序是任意的。
    转移方程:

    [egin{cases} dp_{l,r}+=dp_{l+1,r}qquad S_i=T_l or l>m\ dp_{l,r}+=dp_{l,r-1}qquad S_i=T_r or r>m end{cases} ]

    注意到插入空串的时候前后算是两种,所以没必要特殊处理,把(dp_{i,i-1})初始化成(1)就可以了。
    最终所求就是(dp_{1,m})(dp_{1,n})的总和。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 3010;
    const int mod = 998244353;
    
    int n, m, dp[maxn][maxn];
    string s, t;
    
    bool check(int i, char c){
        return i>m||t[i - 1] == c;
    }
    int main(){
        cin >> s >> t;
        n = s.length(),m = t.length();
        for(int i = 1; i <= n + 1; i++)
            dp[i][i - 1] = 1;
        for(int d = 1; d <= n; d++){
            char c = s[d - 1];
            for(int i = 1, j = d; j <= n; i++, j++){
                if(check(i, c))dp[i][j] = (dp[i][j] + dp[i + 1][j]) % mod;
                if(check(j, c))dp[i][j] = (dp[i][j] + dp[i][j - 1]) % mod;
            }
        }
        int ans = 0;
        for(int i = m; i <= n; i++)ans = (ans + dp[1][i]) % mod;
        cout << ans << "
    ";
        return 0;
    }
    
  • 相关阅读:
    Rust条件编译
    997. Find the Town Judge
    Rust理解所有权借用与引用
    一个16进制占多少个字节?半个字节
    841. Keys and Rooms
    21. Merge Two Sorted Lists
    RustRc和Arc
    652. Find Duplicate Subtrees
    【转载】Centos7安装FastDFS
    金融互联网公司如何保证用户私人信息安全?
  • 原文地址:https://www.cnblogs.com/charles1999/p/12712011.html
Copyright © 2020-2023  润新知