Codeforces Round #633 (Div. 2)题解

A. Filling Diamonds

题意:问 $n$个菱形方块拼成所示的钻石的方案

思路:很明显的是每个图形中有$n$个站着的菱形,选择其中一个其他都会变成躺着的,因此答案为$ n $

#include<iostream>
#include<cstdio>
 using namespace std;
int main(){
    int t,x;
    cin>>t;
    while(t--){
        cin>>x;
        cout<<x<<endl;
    }
    return 0;
}
View Code

B - Sorted Adjacent Differences

题意:给一个数组,要求重新排列后,相邻元素的绝对值不递减

思路:排序后将数组倒着一小一大放置即可

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
 using namespace std;
 typedef long long ll;
 const int maxn=1e5+10;
 ll a[maxn],ans[maxn];
 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);
         int l=1,r=n;
         for(int i=n;i>=1;i--){
             if((n-i)%2==0){
                 ans[i]=a[l++];
             }
            if((n-i)%2==1){
                ans[i]=a[r--];
            }
         }
        for(int i=1;i<=n;i++){
            if(i!=1) printf(" ");
            printf("%d",ans[i]);
        } 
        cout<<endl;
     }
     return 0;
 }
View Code

C - Powered Addition

题意:给一个数组,你可以在第$ x $秒给一些元素加上$2^{x-1}$ ,问多少秒后数组可以变成一个不递减序列

思路:找到数组中一组前后差最大的元素即可,然后判断需要加几秒即可

#include<iostream>
#include<algorithm>
 using namespace std;
 const int maxn=1e5+10;
 int a[maxn];
 int main()
 {
     int t,n;
     scanf("%d",&t);
     while(t--){
         scanf("%d",&n);
         for(int i=1;i<=n;i++) scanf("%d",&a[i]);
         int mi=a[n],flag=0,ret=0;
         for(int i=n-1;i>=1;i--){
             if(a[i]>mi) flag=1,ret=max(ret,a[i]-mi);
             else mi=min(a[i],mi);
         }
        if(!flag) cout<<0<<endl;
        else{
            int x=1,cnt=0;
            while(ret>0){
                ret-=x;
                x*=2;
                cnt++;
            }
            cout<<cnt<<endl;
        }
     }
    return 0;
 }
View Code

D - Edge Weight Assignment

题意:问给一棵无根树每一条边赋值,要求任意两个叶子节点的路径上的边的权值异或和为$0$,求填写方案中权值种类的最大值和最小值

思路:先考虑最小值,最好的情况就是全部都是$1$,那么最小值就为$1$

     但是如果有两个叶子结点之间的距离为奇数的话,异或的结果就不为$1$,参考样例$2$,这时候的最小值就为$3$

   判断叶子节点之间的距离奇偶性一个比较好的方法就可以统计所有的深度,如果又有奇数又又偶数的话,就肯定有两个叶子结点之间距离为偶数

   再来考虑最大值,我们可以试着将所有边权构造为不能的数,但是这样会出现一种情况就是一个父亲节点连接多个叶子,这样是不可能的,这时候答案就为$ n - 1 - x ,x$为符合要求的父亲节点所连接的叶子节点数

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#define mp make_pair
#define pb push_back
#define ll long long
#define kl k<<1
#define kr k<<1|1
using namespace std;
const int manx=1e5+5;
vector<ll>g[manx],ans;
ll de[manx],f[manx];
void dfs(ll u,ll pre){
    de[u]=de[pre]+1;  f[u]=pre;
    for(auto v: g[u]){
        if(g[v].size()==1) ans.pb(u);
        if(v==pre) continue;
        dfs(v,u);
    }
}
int main()
{
     int n,u,v;
     cin>>n;
     for(int i=1;i<n;i++){
        cin>>u>>v;
        g[u].pb(v); g[v].pb(u);
     }
     de[0]=-1;
    dfs(1,0);
    ll f=0,cnt=0,nu=0;
    for(int i=1;i<=n;i++){
        if(g[i].size()==1&&de[i]%2==0) cnt++;
        if(g[i].size()==1&&de[i]%2) nu++;
    }
    if(cnt>=1&&nu>=1) f=1;
    if(f!=0) cout<<"3 ";
    else cout<<"1 ";
    sort(ans.begin(),ans.end());
    ll ma=n-1;
    for(int i=0;i<ans.size();i++)
        if(i){
            if(ans[i]==ans[i-1]) --ma;
        }
    cout<<ma;
    return 0;
}
View Code

 

 

 

posted @ 2020-04-13 13:51  overrate_wsj  阅读(296)  评论(1编辑  收藏  举报