Codeforces Round #633 (Div. 2) Apr/12/2020 22:05UTC+8

比赛链接 https://codeforces.com/contest/1339
比赛记录 https://blog.csdn.net/cheng__yu_/article/details/105395197

A. Filling Diamonds(递推)

在这里插入图片描述
题意:找填充的找方案数
思路:第 n 层比第 n-1 层多了1(最后一列竖着摆)。递归看, f [ n ] = f [ n − 1 ] + 1 。 f [ 1 ] = 1 f[n]=f[n-1]+1。f[1]=1 f[n]=f[n1]+1f[1]=1

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;

int t,n; 

int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		printf("%d\n",n);
	}
	return 0;
}

B. Sorted Adjacent Differences(绝对值)

在这里插入图片描述
思路:排序后,直接从中位数开始交叉放。这样的话,绝对值之差只会越来越大。因为它们距离中位数的距离越来越远

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,mod=1e9+7;
const int inf=0x3f3f3f3f;
ll t,n,a[maxn]; 

int main()
{
	scanf("%lld",&t);
	while(t--)
	{
		scanf("%lld",&n);
		for(int i=1;i<=n;++i)
			scanf("%lld",&a[i]);
		sort(a+1,a+1+n);
		int l,r;
		vector<ll> ans;
		if(n&1)
			l=n/2,r=n/2+2,ans.push_back(a[n/2+1]);
		else
			l=n/2,r=n/2+1;
		while(l>=1)
		{
			ans.push_back(a[l]);
			ans.push_back(a[r]);
			l--,r++;
		}
		for(int i=0;i<=n-1;++i)
			cout<<ans[i]<<" ";
	}
	return 0;
}

C. Powered Addition(二进制)

在这里插入图片描述
思路:因为是2进制,而且每一位都可以选择。如果选择了 t 秒,那么后面的任何数,都是可以到达 2 t 2^t 2t 。因此只需要找绝对值之差最大的数 d 。然后填满这个 d 需要的时间 t t t ,就是答案。
总结

  • 用2进制可以累积任何数
  • 计算 d 需要的时间 t,只需要把它看成是二进制的表示,比如,1011。右移的次数就是位数
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;

int t,n;
ll a[maxn];

int main()
{
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;++i)
            cin>>a[i];
        ll maxx=a[1],d=0;
        for(int i=2;i<=n;++i)
        {
            maxx=max(maxx,a[i]);
            d=max(d,abs(a[i]-maxx));
        }

        int cnt=0;
        while(d)
        {
            d>>=1;
            cnt++;
        }
        cout<<cnt<<"\n";
    }
    return 0;
}

D. Edge Weight Assignment(构造 + DFS)

在这里插入图片描述

题意:给定一颗n个节点的树和n-1,任意两个叶节点之间,路径上边权的异或和为0。求最大和最小的不同边权的数量。

思路

  1. 最小:如果任意两个叶节点之间的距离为偶数,答案为1;如果存在两点之间的距离为奇数,答案为3
  2. 最大:最多为n-1,如果存在两个叶节点的距离为2,则答案 -1

实现

  1. 所有点到根节点的距离同奇或者同偶,则说明任意两点之间的距离为偶数
  2. 距离为2的两个叶节点,只需统计入度为1节点的父节点的叶节点数量,即可计算

总结

  • 叶节点:入度为1。邻接表中找叶节点的父节点也简单,就只有唯一一条边相连
  • 奇数( ≥ 3 \ge 3 3)个数:至少需要3个数,异或和才为0
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;

int n;
vector<int> G[maxn];
int in[maxn],depth[maxn],f[maxn];

void dfs(int u,int fa=-1)
{
    for(auto v : G[u])
    {
        if(v==fa)
            continue;
        depth[v]=depth[u]+1;
        dfs(v,u);
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n-1;++i)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
        in[u]++,in[v]++;
    }

    for(int i=1;i<=n;++i)
        if(in[i]==1)
            f[G[i][0]]++;
    int ans1=n-1;
    for(int i=1;i<=n;++i)
        if(f[i]>=2)
            ans1-=f[i]-1;

    dfs(1);
    bool f1=false,f2=false;
    for(int i=1;i<=n;++i)
    {
        if(in[i]==1)
        {
            if(depth[i]-depth[1]&1)
                f1=true;
            else
                f2=true;
        }
    }
    int ans2=(f1&&f2)?3:1;
    printf("%d %d\n",ans2,ans1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值