Educational Codeforces Round 126 [Rated for Div. 2](A~C)

本文分享了三道编程竞赛题目及其解决方案。A题通过贪心策略,不断交换数组元素实现和的最小化;B题暴力枚举操作次数,找到使所有数变为0的最少数目;C题通过分类讨论,确定使所有树高度相同所需的最少数目。文章适合编程爱好者和竞赛选手阅读,提升算法思维和实战能力。
摘要由CSDN通过智能技术生成

本人太弱了,只能够写三题。因为后一天要赶6点的班车,正赛就没打了,在导论课上补了三题(狗头) 接下来进入正题。

比赛链接:https://codeforces.com/contest/1661

A: Array Balancing

You are given two arrays of length nn: a1,a2,…,an and b1,b2,…,bn.

You can perform the following operation any number of times:

  1. Choose integer index i (1≤i≤n);
  2. Swap ai and bi.

What is the minimum possible sum |a1−a2|+|a2−a3|+⋯+|an−1−an||a1−a2|+|a2−a3|+⋯+|an−1−an| ++ |b1−b2|+|b2−b3|+⋯+|bn−1−bn||b1−b2|+|b2−b3|+⋯+|bn−1−bn| (in other words, ∑i=1n−1(|ai−ai+1|+|bi−bi+1|)∑i=1n−1(|ai−ai+1|+|bi−bi+1|)) you can achieve after performing several (possibly, zero) operations?

Input

The first line contains a single integer tt (1≤t≤40001≤t≤4000) — the number of test cases. Then, tt test cases follow.

The first line of each test case contains the single integer nn (2≤n≤252≤n≤25) — the length of arrays aa and bb.

The second line of each test case contains n integers a1,a2,…,an (1≤ai≤1e9) — the array a.

The third line of each test case contains n integers b1,b2,…,bn (1≤bi≤1e9) — the array b.

Output

For each test case, print one integer — the minimum possible sum ∑i=1n−1(|ai−ai+1|+|bi−bi+1|)∑i=1n−1(|ai−ai+1|+|bi−bi+1|).

题意大概是:给你两个数组,数组a和数组b,每次可以选取一个下标i,交换a[i]和b[i].问最终

| a[1]-a[2] |+| a[2]-a[3] |+...+| a[n]+a[n+1] |+ | b[1]-b[2] |+| b[2]-b[3] |+...+| b[n]+b[n+1] |的最小值

解析:其实题目就是一个贪心的过程(怎么说呢?迷迷糊糊就AC了),我们可以从1遍历到n,如果abs(a[i]-a[i+1])+abs(b[i]-b[i+1])>abs(b[i]-a[i+1])+abs(a[i]-b[i+1])  说明交换a[i+1]和b[i+1]的贡献会更小,所以进行交换。最后进行求和就完事了。

AC代码如下

#include<bits/stdc++.h>
using namespace std;
int a[35],b[35];
int main( ){
	int t,n;
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;++i){
			cin>>a[i];
		}
		for(int i=1;i<=n;++i){
			cin>>b[i];
		}
		for(int i=1;i<=n;++i){
			if(abs(a[i]-a[i+1])+abs(b[i]-b[i+1])>abs(b[i]-a[i+1])+abs(a[i]-b[i+1])){
				swap(a[i+1],b[i+1]);
			}
		}
		long long sum=0;
		for(int i=1;i<n;++i){
			sum+=abs(a[i]-a[i+1])+abs(b[i]-b[i+1]);
		}
		cout<<sum<<endl;
	}
	
} 

 

B. Getting Zero

Suppose you have an integer v. In one operation, you can:

  • either set v=(v+1)mod32768
  • or set v=(2⋅v)mod32768.

You are given nn integers a1,a2,…,an.What is the minimum number of operations you need to make each aiai equal to 0?

Input

The first line contains the single integer n (1≤n≤327681≤n≤32768) — the number of integers.

The second line contains nn integers a1,a2,…,an (0≤ai<327680).

题意大概是:给你n个数,通过这两种操作(第一种 v=(v+1)%32768,第二种(2*v)%32768) 把它变成0,问你最少操作数。

解析:当时写这题一点思路都没有。但其实通过本题不难发现,如果一直进行第二种操作把它变成0的话,最多也只要20多次的操作数。所以我们就可以快乐的暴力了。所以我们只要遍历第一种操作的个数,然后计算此时需要第二次操作的最小个数。最后取个最小值就行了哈。

#include<bits/stdc++.h>
using namespace std;
int Min;
int main( ) {
	int n,x;
	cin>>n;
	while(n--) {
		Min=1e9;
		cin>>x;
		int cnt=0;
		for(int j=0; j<=100; ++j) {
			int sum=x+j;
			sum=sum%32768;
			cnt=0;
			for(int i=1; i<=20; ++i) {
				if(sum==0) break;
				sum=sum*2;
				sum=sum%32768;
				cnt++;
			}
			Min=min(Min,cnt+j);
		}
		cout<<Min<<endl;
	}
}

C. Water the Trees

There are nn trees in a park, numbered from 1 to n. The initial height of the ii-th tree is hihi.

You want to water these trees, so they all grow to the same height.

The watering process goes as follows. You start watering trees at day 11. During the jj-th day you can:

  • Choose a tree and water it. If the day is odd (e.g. 1,3,5,7,…), then the height of the tree increases by 1. If the day is even (e.g. 2,4,6,8,…), then the height of the tree increases by 2.
  • Or skip a day without watering any tree.

Note that you can't water more than one tree in a day.

Your task is to determine the minimum number of days required to water the trees so they grow to the same height.

You have to answer tt independent test cases.

Input

The first line of the input contains one integer t(1≤t≤2⋅1e4) — the number of test cases.

The first line of the test case contains one integer n (1≤n≤3⋅1e5) — the number of trees.

The second line of the test case contains n integers h1,h2,…,hn(1≤hi≤1e9), where hi is the height of the i-th tree.

It is guaranteed that the sum of nn over all test cases does not exceed 3⋅1e5 (∑n≤3⋅1e5).

Output

For each test case, print one integer — the minimum number of days required to water the trees, so they grow to the same height.

题意大概是给你一个数组,在第i(i为奇数)次的操作中 你可以任选一个数进行加1,在i(i为偶数)次的操作中 你可以任选一个数进行加2.而且每次操作,你也可以选择跳过不做。问你要把数组中所有的数变成相等,最少要几次操作。

很多大佬选择二分求解,我也尝试过,但最终wa爆了。所以本蒟蒻选择了分类讨论了(TAT)。

解析:我们先找出这个数组的最大值Max,然后再求出其余的数达到这个Max,需要多少次偶数次操作和多少次奇数次操作。偶数次操作,我这里记为even,奇数次操作我记为odd。接下来就是愉快的分类讨论了。

1:当odd=even或者odd=even+1时候 答案为odd+even

2:当odd>even时候 答案为2*odd-1

3:当odd<even时候,我们就通过分配尽量把abs(odd-even)变小

      i:当(even-odd)刚好整除以3  odd变为odd + (even-odd) / 3 * 2,;

      even变为even-(even-odd)/3 答案为odd+even

      II : 当(even-odd)不整除时候,odd变为odd + (even-odd) / 3 * 2;

      even变为even-(even-odd)/3 此时又又要分两种讨论

            1:odd大于even 答案为odd+even;

             2:odd小于even 答案为odd+even+1;

讨论结束,但是陷阱就在这里。我们还要在进行一次操作,将Max变为Max+1(因为原数据求出来的even可能为0,从而无法达到操作最小值)。重复上述操作。再取最小值,别忘了开long long 哦

#include<bits/stdc++.h>
using namespace std;
long long a[300005];
int main( ) {
	int t,n;
	cin>>t;
	while(t--) {
		cin>>n;
		long long Max=0;
		for(int i=1; i<=n; ++i) {
			cin>>a[i];
			Max=max(Max,a[i]);
		}
		for(int i=1; i<=n; ++i) {
			a[i]=Max-a[i];
		}
		long long odd=0;
		long long even=0;
		for(int i=1; i<=n; ++i) {
			odd+=a[i]&1;
			even+=a[i]/2;
		}
		long long Min=1e18;
		if(odd==even||odd==even+1) Min=min(Min,odd+even);
		else if(odd<even) {
			if((even-odd)%3==0) {
				Min=min(Min,(odd+(even-odd)/3*2)*2);
			} else {
				if((odd+(even-odd)/3*2)>even-(even-odd)/3) {
					Min=min(Min,odd+(even-odd)/3*2+even-(even-odd)/3);
				} else {
					Min=min(Min,1+odd+(even-odd)/3*2+even-(even-odd)/3);
				}
			}
		} else {
			Min=min(Min,2*odd-1);
		}
		odd=0;
		even=0;
		for(int i=1; i<=n; ++i) {
			odd+=(a[i]+1)&1;
			even+=(a[i]+1)/2;
		}
		if(odd==even||odd==even+1) Min=min(Min,odd+even);
		else if(odd<even) {
			if((even-odd)%3==0) {
				Min=min(Min,(odd+(even-odd)/3*2)*2);
			} else {
				if((odd+(even-odd)/3*2)>even-(even-odd)/3) {
					Min=min(Min,odd+(even-odd)/3*2+even-(even-odd)/3);
				} else {
					Min=min(Min,1+odd+(even-odd)/3*2+even-(even-odd)/3);
				}
			}
		} else Min=min(Min,odd*2-1);
		cout<<Min<<endl;
	}
}

第一次发博客,确实有点粗糙。最后希望大家能够多多体谅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值