Codeforces Round #633 (Div. 2) 题解

题目链接

A - Filling Diamonds

题目大意:给你n个菱形方块问你拼成他所示的钻石形状有几种?

题解:主要看立着的那个方块的位置,不难发现是 n n n种。

代码

#include 
 
using namespace std;

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

B - Sorted Adjacent Differences

题目大意:给你一个数组,你需要重新排列这个数组的元素,使得相邻两个元素的差值呈非递减。

题解:先将数组排个序,然后让最中间的那个元素安排在第一个,依次向两边扩展就好了。

代码

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e6 + 5;
const int inf = 0x3f3f3f3f;
 
 
int a[maxn];
int ans[maxn];
void solve()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
	scanf("%d",&a[i]);
sort(a+1,a+1+n);
int cnt=0;
int mid=n/2+1;
int cnt2=0;
ans[++cnt]=a[mid];
cnt2++;
while(cnt<n)
{
if(mid-cnt2>=1)
	ans[++cnt]=a[mid-cnt2];
if(mid+cnt2<=n)
	ans[++cnt]=a[mid+cnt2];
cnt2++;
}
for(int i=1;i<=n;i++)
{
	if(i==n)
		printf("%d\n",ans[i]);
	else printf("%d ",ans[i]);
}
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

C - Powered Addition

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

题解:当遇到 a i + 1 < a i a_{i+1}ai+1<ai我们只要让 a i + 1 a_{i+1} ai+1加上差值就是最优,计算差值所需要的的时间,并更新 a i + 1 a_{i+1} ai+1

代码

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e6 + 5;
const int inf = 0x3f3f3f3f;
 
 
ll a[maxn];
int ck(ll temp)
{
	ll te=1;
	for(int i=0;i<=40;i++){
		if(te==temp)
			return i+1;
		else if(te>temp)
			return i;
		te*=2;
	}
}
void solve()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
	scanf("%lld",&a[i]);
int ans=0;
for(int i=1;i<n;i++)
{
	if(a[i]>a[i+1])
	{
		ll temp=a[i]-a[i+1];
        ans=max(ans,ck(temp));
        a[i+1]=a[i];
	}
}
printf("%d\n",ans);
}
int main()
{
    int t;scanf("%d",&t);while(t--)
    solve();
	return 0;
}

D - Edge Weight Assignment

题目大意:给你一颗树,你需给没一条边赋一个正的权值(题目说整个权值可以很大,意思应该就是不设上限),要求任意两个叶子节点的路径上的边的权值异或和为 0 0 0。问你满足这样的条件下,填写的数字的种类的最大值和最小值。

题解:首先我们来看最小值,如果说任意两个叶子节点的距离都为偶数,那么明显可以将所有边填为同一个数字,最小值就为 1 1 1,如果其中有奇数,那么最小值只能是 3 3 3,而且我们其实只需要判断从其中一个叶子节点出发到其他叶子节点的距离是不是偶数就够了(都判断会超时,而且没必要)。然后我们来看最大值,理想条件肯定是每一条边都填上不同的数字,那么最大值为 n − 1 n-1 n1,但是当 m m m个叶子节点连接同一个节点时,很明显这 m m m个叶子节点的领边必须填相同的数,我们在 n − 1 n-1 n1的基础上减 m − 1 m-1 m1就好了。

代码

#include 
 
using namespace std;
 
#define mem(a, x) memset(a, x, sizeof(a))
#define IOS std::ios::sync_with_stdio(false)
#define ls o<<1
#define rs o<<1|1
#define test(a) cout<
#define exp 0.000001
#define pb push_back
typedef long long ll;
const int mod = 1e9+7;
const int maxn = 2e6 + 5;
const int inf = 0x3f3f3f3f;
 
 
vector<int> ve[maxn];
int deg[maxn];
int dis[maxn];
int vis[maxn];
void bfs(int rt)
{
mem(vis,0);
mem(dis,-1);
dis[rt]=0;
queue<int> q;
q.push(rt);
vis[rt]=1;
while(!q.empty())
{
	int temp=q.front();
	q.pop();
	for(int i=0;i<ve[temp].size();i++)
	{
		if(!vis[ve[temp][i]])
		{
			q.push(ve[temp][i]);
			vis[ve[temp][i]]=1;
			dis[ve[temp][i]]=dis[temp]+1;
		}
	}
}
}
void solve()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
	int a,b;
	scanf("%d%d",&a,&b);
	ve[a].pb(b);
	ve[b].pb(a);
	deg[a]++;
	deg[b]++;
}
bfs(1);
int rt,now=0;
for(int i=1;i<=n;i++)
{
	if(dis[i]>now)
	{
		now=dis[i];
		rt=i;
	}
}
bfs(rt);
int flag=1;
now=n-1;
for(int i=1;i<=n;i++)
{
	if(deg[i]==1&&dis[i]&1)
		flag=0;
	int cnt=0;
	for(int j=0;j<ve[i].size();j++)
		if(deg[ve[i][j]]==1)
			cnt++;
	now-=max(cnt-1,0);
}
if(flag)
printf("1 ");
else printf("3 ");
printf("%d\n",now);
}
int main()
{
    solve();
	return 0;
}

你可能感兴趣的:(codeforces)