Codeforces Round #633 (Div. 2) ABC+D详解

如果有什么讲的不清楚的欢迎留言私信交流~

A - Filling Diamonds

题意:问n个菱形方块拼成所示的钻石的方案。
思路: 很明显的是每个图形中有n个站着的菱形,选择其中一个其他都会变成躺着的,因此答案为n。

#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;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}
 
const int manx=1e5+5;
const int mo=998244353;
 
ll n;
 
int main(){
    ll p=read();
    while(p--){
        cin>>n;
        cout<<n<<endl;
    }
    return 0;
}

B - Sorted Adjacent Differences

题意:给你一个数组,你需要重新排列这个数组的元素,使得相邻两个元素的差值呈非递减。
思路:为了保持每两个数之间的间隔变大,可以选择排序后从 ( n + 1 ) / 2 (n+1)/2 开始,偶数情况下右边会多一个所以 w h i l e while 里面先输出右边再输出左边,这样保证间隔来回递增。

#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;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}
 
const int manx=1e5+5;
const int mo=998244353;
 
ll a[manx];
ll n;
 
int main(){
    ll p=read();
    while(p--){
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        ll mid=(n+1)/2;
        sort(a+1,a+1+n);
        cout<<a[mid];
        ll l=mid-1,r=mid+1;
        while(l!=0 || r!=n+1){
            if(r!=n+1) cout<<" "<<a[r++];
            if(l!=0) cout<<" "<<a[l--];
        }
        cout<<endl;
    }
    return 0;
}

C - Powered Addition

题意:给你一个数组,你可以在第x秒选一些元素让它们都加上 2 x 1 2的(x−1)幂 ,问至少需要多少秒可以使数组变成非递减的数组。

思路:找到最大的间隔,然后枚举 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;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}
 
const int manx=1e5+5;
const int mo=998244353;
 
ll a[manx];
ll n;
 
int main(){
    ll p=read();
    while(p--){
        n=read();
        for(int i=1;i<=n;i++) a[i]=read();
        ll mi=a[n],ma=0;
        for(int i=n-1;i>=1;i--){
            if(a[i]>mi) ma=max(ma,a[i]-mi);
            mi=min(mi,a[i]);
        }
        ll x=1,cnt=0;
        if(!ma) cout<<0<<endl;
        else{
            while(ma>0){
                ++cnt; ma-=x; x<<=1;
            }
            cout<<cnt<<endl;
        }
    }
    return 0;
}

D - Edge Weight Assignment

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

  1. 先给出结论再解释:
  2. 如果叶子节点的深度有奇有偶,那么最小值为3,否则为1;
  3. 最大值为 n 1 x n-1-x ,x为连接与同一节点的超过1的叶子数目。
  4. 首先讲一下最小值,如果叶子节点的深度都为偶数/奇数,那么任意两个叶子间的距离为偶数(偶数+偶数=偶数 奇数+奇数=偶数),则可全1;否则的话只要两个叶子间距离为奇数,那么无法全1,只要选择3个叶子节点为1 2 3,其他全1;
  5. 最大值的话,不难想到n个点只有n-1条边,那么最大值可定为n-1,但是如果一个节点 fa 如果连接多个叶子的话,而且这些叶子之间只隔着两条边,所以这些叶子到 fa 的边权都是相同的 。那么说明假设 一个节点连接 x (x>1) 个叶子,那么就有x条边相同,因此最大值要减去这一部分的贡献,所以最大值为 n 1 x n-1-x ,x为连接与同一节点的超过1的叶子数目。
#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;
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();return s*w;}
void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}void put3(){ puts("-1"); }
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){ans = (ans*a)%p;--b;}a =
(a*a)%p;b >>= 1;}return ans%p;}
 
const int manx=1e5+5;
const int mo=998244353;
 
vector<ll>g[manx],fa;
ll n,ji,ou;
ll d[manx];
 
void dfs(ll u,ll pre){
    d[u]=d[pre]+1;
    for(auto v: g[u]){
        if(v==pre) continue;
        dfs(v,u);
    }
    if(g[u].size()==1){
        if(d[u]&1) ji++;
        else ou++;
        if(pre==0) fa.pb(g[u][0]);
        else fa.pb(pre);
    }
}
 
int main(){
    n=read();
    for(int i=1;i<n;i++){
        ll u=read(),v=read();
        g[u].pb(v); g[v].pb(u);
    }
    dfs(1,0);
    if(ji&&ou) cout<<3<<" ";
    else cout<<1<<" ";
    ll ma=n-1;
    sort(fa.begin(),fa.end());
    for(int i=1;i<fa.size();i++)
        if(fa[i]==fa[i-1]) --ma;
    cout<<ma;
    return 0;
}

以上,如果有什么讲的不清楚的欢迎留言私信交流~

原创文章 96 获赞 109 访问量 4万+

猜你喜欢

转载自blog.csdn.net/JiangHxin/article/details/105481826