Codeforces Round #642 (Div. 3)------题目+题解+代码(A、B、C、D)

本文解析了CodeForces平台上的四道算法竞赛题目,包括数组构造、数组元素交换、棋盘移动策略及数组构建策略,提供了详细的解题思路与代码实现。

A. Most Unstable Array

来源:http://codeforces.com/contest/1353/problem/A

You are given two integers n and m. You have to construct the array a of length n consisting of non-negative integers (i.e. integers greater than or equal to zero) such that the sum of elements of this array is exactly m and the value ∑i=1n−1|ai−ai+1| is the maximum possible. Recall that |x| is the absolute value of x.

In other words, you have to maximize the sum of absolute differences between adjacent (consecutive) elements. For example, if the array a=[1,3,2,5,5,0] then the value above for this array is |1−3|+|3−2|+|2−5|+|5−5|+|5−0|=2+1+3+0+5=11. Note that this example doesn’t show the optimal answer but it shows how the required value for some array is calculated.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤104) — the number of test cases. Then t test cases follow.

The only line of the test case contains two integers n and m (1≤n,m≤109) — the length of the array and its sum correspondingly.

Output
For each test case, print the answer — the maximum possible value of ∑i=1n−1|ai−ai+1| for the array a consisting of n non-negative integers with the sum m.

Example
inputCopy
5
1 100
2 2
5 5
2 1000000000
1000000000 1000000000
outputCopy
0
2
10
1000000000
2000000000
Note
In the first test case of the example, the only possible array is [100] and the answer is obviously 0.

In the second test case of the example, one of the possible arrays is [2,0] and the answer is |2−0|=2.

In the third test case of the example, one of the possible arrays is [0,2,0,3,0] and the answer is |0−2|+|2−0|+|0−3|+|3−0|=10.

题意:
给你两个数n和m,让你找出n个和为m的数,并且邻位数的差的绝对值最大,并输出最大值。
思路:
毕竟是A题,就超简单的方向上思考,通过观察和结合样例可以发现是有规律可循的


n=1:				ans=0
很显然只有一项时ans为0

n=2:				ans=m	
只有两项时,两个数只能分为 0 m ,才能实现最大

n=3:				ans=2*m
将三个数分为0 m 0,此时最大

n>3时:             ans=2*m
和n=3时相同,其他项均为零即可

找到规律后,这道题就解决了

代码:

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
int main() 
{
	int t;
	cin >> t;
	int n, m;
	while (t--)
	{
		cin >> n >> m;
		if (n == 1)cout << '0' << endl;
		else if (n == 2)cout << m << endl;
		else cout << 2 * m << endl;
 
	}
	return 0;
}

B. Two Arrays And Swaps

来源:http://codeforces.com/contest/1353/problem/B

You are given two arrays a and b both consisting of n positive (greater than zero) integers. You are also given an integer k.

In one move, you can choose two indices i and j (1≤i,j≤n) and swap ai and bj (i.e. ai becomes bj and vice versa). Note that i and j can be equal or different (in particular, swap a2 with b2 or swap a3 and b9 both are acceptable moves).

Your task is to find the maximum possible sum you can obtain in the array a if you can do no more than (i.e. at most) k such moves (swaps).

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤200) — the number of test cases. Then t test cases follow.

The first line of the test case contains two integers n and k (1≤n≤30;0≤k≤n) — the number of elements in a and b and the maximum number of moves you can do. The second line of the test case contains n integers a1,a2,…,an (1≤ai≤30), where ai is the i-th element of a. The third line of the test case contains n integers b1,b2,…,bn (1≤bi≤30), where bi is the i-th element of b.

Output
For each test case, print the answer — the maximum possible sum you can obtain in the array a if you can do no more than (i.e. at most) k swaps.

Example
inputCopy
5
2 1
1 2
3 4
5 5
5 5 6 6 5
1 2 5 4 3
5 3
1 2 3 4 5
10 9 10 10 9
4 0
2 2 4 3
2 4 2 3
4 4
1 2 2 1
4 4 5 4
outputCopy
6
27
39
11
17
Note
In the first test case of the example, you can swap a1=1 and b2=4, so a=[4,2] and b=[3,1].

In the second test case of the example, you don’t need to swap anything.

In the third test case of the example, you can swap a1=1 and b1=10, a3=3 and b3=10 and a2=2 and b4=10, so a=[10,10,10,4,5] and b=[1,9,3,2,9].

In the fourth test case of the example, you cannot swap anything.

In the fifth test case of the example, you can swap arrays a and b, so a=[4,4,5,4] and b=[1,2,2,1].

题意:
给你两个长度为n的数组a,b,交换a和b中的元素,并且最多交换k次,是a数组所有元素的和最大。

思路:
贪心的问题,思路比较好想,就是用a数组较小的元素去换b数组中较大的元素,若数组a中最小值小于b中最大值,将其用b中最大值替换,具体实现见代码

代码:

#include<iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int a[35], b[35];
int cmp(int a, int b) 
{
	return a > b;
}
int main() 
{
	int t, n, k, i, sum;
	scanf("%d", &t);
	while (t--) 
	{
		sum = 0;
		scanf("%d%d", &n, &k);
		for (i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		for (i = 1; i <= n; i++)
			scanf("%d", &b[i]);
		sort(a + 1, a + 1 + n);//升序
		sort(b + 1, b + 1 + n, cmp);//降序
		for (i = 1; i <= k; i++)
		{
			if (a[i] < b[i])
				swap(a[i], b[i]);
			else
				break;
		}
		for (i = 1; i <= n; i++)
			sum += a[i];
		printf("%d\n", sum);
	}
	return 0;
}

C. Board Moves

来源:http://codeforces.com/contest/1353/problem/C

You are given a board of size n×n, where n is odd (not divisible by 2). Initially, each cell of the board contains one figure.

In one move, you can select exactly one figure presented in some cell and move it to one of the cells sharing a side or a corner with the current cell, i.e. from the cell (i,j) you can move the figure to cells:

(i−1,j−1);
(i−1,j);
(i−1,j+1);
(i,j−1);
(i,j+1);
(i+1,j−1);
(i+1,j);
(i+1,j+1);
Of course, you can not move figures to cells out of the board. It is allowed that after a move there will be several figures in one cell.

Your task is to find the minimum number of moves needed to get all the figures into one cell (i.e. n2−1 cells should contain 0 figures and one cell should contain n2 figures).

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤200) — the number of test cases. Then t test cases follow.

The only line of the test case contains one integer n (1≤n<5⋅105) — the size of the board. It is guaranteed that n is odd (not divisible by 2).

It is guaranteed that the sum of n over all test cases does not exceed 5⋅105 (∑n≤5⋅105).

Output
For each test case print the answer — the minimum number of moves needed to get all the figures into one cell.

Example
inputCopy
3
1
5
499993
outputCopy
0
40
41664916690999888
题意:
给你一个n * n的方格,其中每个方格内都有一个数字,它能向周围的八个方格任意移动,现在将所有的数字都移动到一个方格中,问最少需要多少移动步

思路:
很容易就想到最后的点肯定是中心点,然后再仔细观察发现,以中心点为基点,周围的第一圈只需要一步就能移动到中心点,而第二圈需要两步,第三圈需要三步,以此类推,第n圈需要n步。
这样就找到了规律
其中每圈有(i-1)*4个方格,圈数为 i/2

代码:

#include<iostream>
using namespace std;
typedef long long ll;
const ll N = 5e5 + 5;
ll res[N];
int main()
{
	int t; 
	ll n;
	cin >> t;
	for (ll i = 3; i <= N; i = i + 2)
	{
		res[i] = (i - 1) * 4 * (i / 2);
		res[i] += res[i - 2];
	}
	while (t--)
	{
		cin >> n;
		cout << res[n] << endl;

	}
}

D. Constructing the Array

来源:http://codeforces.com/contest/1353/problem/D

You are given an array a of length n consisting of zeros. You perform n actions with this array: during the i-th action, the following sequence of operations appears:

Choose the maximum by length subarray (continuous subsegment) consisting only of zeros, among all such segments choose the leftmost one;
Let this segment be [l;r]. If r−l+1 is odd (not divisible by 2) then assign (set) a[l+r2]:=i (where i is the number of the current action), otherwise (if r−l+1 is even) assign (set) a[l+r−12]:=i.
Consider the array a of length 5 (initially a=[0,0,0,0,0]). Then it changes as follows:

Firstly, we choose the segment [1;5] and assign a[3]:=1, so a becomes [0,0,1,0,0];
then we choose the segment [1;2] and assign a[1]:=2, so a becomes [2,0,1,0,0];
then we choose the segment [4;5] and assign a[4]:=3, so a becomes [2,0,1,3,0];
then we choose the segment [2;2] and assign a[2]:=4, so a becomes [2,4,1,3,0];
and at last we choose the segment [5;5] and assign a[5]:=5, so a becomes [2,4,1,3,5].
Your task is to find the array a of length n after performing all n actions. Note that the answer exists and unique.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤104) — the number of test cases. Then t test cases follow.

The only line of the test case contains one integer n (1≤n≤2⋅105) — the length of a.

It is guaranteed that the sum of n over all test cases does not exceed 2⋅105 (∑n≤2⋅105).

Output
For each test case, print the answer — the array a of length n after performing n actions described in the problem statement. Note that the answer exists and unique.

Example
inputCopy
6
1
2
3
4
5
6
outputCopy
1
1 2
2 1 3
3 1 2 4
2 4 1 3 5
3 4 1 5 2 6

题意:
输入一个n,表示有一个长度为n且全为0的数组。现在需要做出n次操作,操作有两种。
第一种是先选出一个长度最长的连续的0的区间,如果有多个这样的区间且长度相同,选择最左端的一个区间。
第二个操作是,如果该区间的长度为奇数,那么将数组的第(l+r)/2为设为i,如果该区间长度为偶数,将数组的第(l+r-1)/2位设为i。
直到n次操作结束,该数组被填满,有且只有唯一的答案,输出该数组。

思路:
思路首先可以想到模拟,每次去找最符合要求的区间,然后填上数字。
然后想到了用优先队列来模拟这个过程,优先选择区间长度最长的,如果相同,那么就选择最靠左端的,这样就相当于模拟一样的实现了这个过程。

代码:

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
struct Node {
    int l, r;
    bool operator <(const Node& a) const {
        return a.r - a.l == r - l ? a.l < l : a.r - a.l > r - l;
    }
}cur;
int pre[200005];
int n, T;

int main()
{
    cin>>T;
    while (T--) 
    {
        cin >> n;
        memset(pre, 0, sizeof(pre));
        priority_queue<Node> q;
        q.push(Node{ 1, n });
        for (int i = 1; i <= n; i++) 
        {
            cur = q.top();
            q.pop();
            int mid = (cur.l + cur.r) / 2;
            pre[mid] = i;

            if (mid - cur.l != 0) 
                q.push(Node{ cur.l, mid - 1 });

            if (cur.r - mid != 0) 
                q.push(Node{ mid + 1, cur.r });
        }
        for (int i = 1; i <= n; i++) 
           cout<<pre[i]<<' ';
        cout << endl;
    }
    return 0;
}

如有不足之处,请指正~

Codeforces Round 1036 是一场同时面向 Div.1 和 Div.2 参赛者的比赛,通常这类比赛会包含多个具有挑战性的编程题目,涵盖算法、数据结构、数学等多个领域。比赛的题解题目信息可以帮助参赛者回顾解题思路,提升编程能力。 ### 比赛基本信息 - **比赛名称**:Codeforces Round #1036 (Div. 1 and Div. 2) - **比赛时间**:具体时间为 UTC+X(根据实际举办日期和时间表) - **比赛链接**:[Codeforces 官方页面](https://codeforces.com/contest/1343) - **题解发布位置**:通常在比赛结束后不久,官方或社区成员会在 Codeforces 博客、GitHub 或其他技术平台上发布题解### 题目类型与难度分布 该轮比赛通常包括 5 到 7 道题目,难度从简单实现到复杂算法不等。例如: - **A题**:通常是简单的模拟或数学问题。 - **B题**:可能涉及字符串处理或基础贪心策略。 - **C题**:中等难度,可能需要掌握基本的数据结构如数组、排序等。 - **D题及以后**:较高难度,可能涉及图论、动态规划、数论等高级算法。 ### 参赛情况与亮点 - **参与人数**:通常超过 10,000 名选手参加。 - **热门话题**:比赛中某些题目可能会引发广泛讨论,尤其是那些需要用到巧妙构造或优化技巧的问题。 - **知名选手表现**:顶尖选手如 tourist、Um_nik 等通常会以极快的速度完成所有题目,并占据排行榜前列。 ### 示例代码片段 以下是一个典型的 Codeforces 题目解法示例,适用于某道中等难度题目: ```cpp #include <bits/stdc++.h> using namespace std; int main() { int t; cin >> t; while(t--) { long long l, r; cin >> l >> r; // 假设 e 是一个预处理好的符合条件的数组 // 使用二分查找来统计区间 [l, r] 内的有效数字个数 long long ans = upper_bound(e.begin(), e.end(), r) - lower_bound(e.begin(), e.end(), l); cout << ans << endl; } return 0; } ``` ### 题解资源推荐 - **Codeforces 官方博客**:通常会有详细的题解和作者说明。 - **GitHub 仓库**:许多参赛者会将自己的解法上传至 GitHub,便于他人学习。 - **知乎专栏 / 优快云 / 博客园**:中文社区中也常有高质量的赛后总结与分析文章。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值