• Codeforces Round #633 (Div. 2)


    A. Filling Diamonds

    题意:

    (交的时候也没搞懂这个题意,犹豫好久)用一个菱形覆盖一个"4n−2triangles"的不同覆盖方法

    思路:

    可以看出来有n种覆盖方法

    代码:

    #include<iostream>
    #include<string.h>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<string>
    #include<set>
    #include<map>
    using namespace std;
    typedef pair<int,int> PII;
    typedef long long LL;
    const int N=100010;
    int main(){
        int T;
        cin>>T;
        while(T--){
            int n;
            cin>>n;
            cout<<n<<endl;
        }
        return 0;
    }
    

    B. Sorted Adjacent Differences

    题意:

    给出一个长度为n的序列:(a_1,a_2,…,a_n),构造一种序列重排后满足:(|a_1−a_2|≤|a_2−a_3|≤…≤|a)n-1(−a_n|),输出任意一种方案。

    思路:

    这种题我们一般都先按从小到大排序,然后找到某种合适的顺序。排序后可以这样构造:(a_1)(a_n)的差值是最大的,然后让(a_1,a_n)排到最后,(a_1)(a)n-1的差小于等于(a_1)(a_n)的差,但是大于不包含(a_n)的其他所有。所有用双指针从前和从后接替加入。

    代码:

    #include<iostream>
    #include<string.h>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<string>
    #include<set>
    #include<map>
    using namespace std;
    typedef pair<int,int> PII;
    typedef long long LL;
    const int N=100010;
    int a[N];
    vector<int> v;
    int main(){
        int T,n;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(int i=1;i<=n;++i){
                scanf("%d",&a[i]);
            }
            sort(a+1,a+1+n);
            v.clear();
            for(int i=1;i<=n/2;++i){
                v.push_back(a[i]);
                v.push_back(a[n-i+1]);
            }
            if(n%2){
                v.push_back(a[n/2+1]);
            }
            reverse(v.begin(),v.end());
            for(auto it: v) cout<<it<<" ";
            cout<<endl;
        }
        return 0;
    }
    

    C. Powered Addition

    题意:

    给出一个序列长度为n的序列,然后可以进行无数次操作,第i次可以选择任意个数(可以一个都不选),将其加上2i-1,求将序列变成非降序序列的最少操作次数。 (1≤n≤10^5,−10^9≤a_i≤10^9)

    思路:

    我们让(a[i-1]>a[i],t=a[i-1]-a[i]),t的二进制最高位1的位数就是我们使得a[i-1]<=a[i]的最小操作次数,所以当我们让a[i-1]=a[i]使用的是最小操作次数,且对于后面的限制更小,所以枚举所有不合法的前后差值,更新最高位1的位数就是答案。

    代码:

    #include<iostream>
    #include<string.h>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<string>
    #include<set>
    #include<map>
    using namespace std;
    typedef pair<int,int> PII;
    typedef long long LL;
    long long a[100010],p[60];
    int main(){
        int T;
        p[0]=1;
        for(int i=1;i<60;++i){
            p[i]=p[i-1]*2;
        }
        scanf("%d",&T);
        while(T--){
            int n;
            scanf("%d",&n);
            for(int i=1;i<=n;++i){
                scanf("%lld",&a[i]);
            }
            int ans=0;
            for(int i=2;i<=n;++i){
                if(a[i-1]>a[i]){
                    LL t=a[i-1]-a[i];
                    int res=0;
                    //cout<<t<<endl;
                    while(t){
                        res++;
                        t>>=1;
                    }
                    ans=max(ans,res);
                    a[i]=a[i-1];
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    

    D. Edge Weight Assignment

    题意:

    给出一个无权树,给每个边上赋一个权值,使得每两个叶子节点之间的路径边权异或和位0,求权值数的种类的最少和最多各为多少。(3≤n≤10^5)

    思路:

    数最少的情况:
    当两个叶子节点之间的边数为偶数,那么这条路上的只用一种数就可以了。当边数奇数时,我们也只需要三个数就可以了:假设a-b之间边数为奇数,对于这一条单一的路径至少需要三个数是显然的,假设这条路径上有别另一条分支点d引出叶子节点c,c到d的边可以构造成异或和等于a到d的异或和,这样c到a的异或和为0,由于c到b和a到b一样,所以c到b异或和也为0.
    数最多的情况:
    若n-1条边权值都不相等,假设a到b的m条边都不相等,异或和为0,若有a的父亲节点d有另一个儿子节点c也是叶子,那么a到b的边数是2,则a到d和c到d的边权值相等,所以遍历一遍减去满足这种情况的边数。

    代码:

    #include<iostream>
    #include<string.h>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<string>
    #include<set>
    #include<map>
    using namespace std;
    typedef pair<int,int> PII;
    typedef long long LL;
    const int N=100010;
    vector<int> g[N];
    int dis[N],ans1,ans2;
    bool dfs1(int u,int fa){
        dis[u]=dis[fa]+1;
        if(dis[u]%2&&g[u].size()==1) {
            ans1=3;
           //cout<<u<<endl;
            return true;
        }
        for(int i=0;i<g[u].size();++i){
            int v=g[u][i];
            if(v==fa) continue;
            if(dfs1(v,u)) return true;
        }
        return false;
    }
    void dfs2(int u,int fa){
        int cnt=0;
        for(int i=0;i<g[u].size();++i){
            int v=g[u][i];
            if(fa==v) continue;
            if(g[v].size()==1) cnt++;
            else dfs2(v,u);
        }
        if(cnt>0){
            ans2-=cnt-1;
        }
    }
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1,u,v;i<n;++i) {
            cin>>u>>v;
            g[u].push_back(v);
            g[v].push_back(u);
        }
        ans1=1,ans2=n-1;
        int f1=0,f2=0;
        for(int i=1;i<=n;++i){
            if(g[i].size()==1&&!f1){
                dis[0]=-1;
                dfs1(i,0);f1=1;
            }
            if(g[i].size()>1&&!f2) {
                dfs2(i,0);f2=1;
            }
        }
        cout<<ans1<<" "<<ans2<<endl;
        return 0;
    }
    
  • 相关阅读:
    Python之数学(math)和随机数(random)
    《图解HTTP》读书笔记
    leetcode1008
    leetcode1007
    leetcode1006
    leetcode1005
    leetcode218
    leetcode212
    leetcode149
    leetcode140
  • 原文地址:https://www.cnblogs.com/jjl0229/p/12702603.html
Copyright © 2020-2023  润新知