Codeforces Global Round 19

这篇博客讨论了两个算法问题:一是对数组的前后缀进行非降序排序,二是判断能否通过特定操作将石子移动到两端。在第一个问题中,只要原始数组存在逆序对,就会在某次排序中出现非降序。第二个问题涉及移动石子,当石子分布满足特定条件时,可以将所有石子移动到两端。博客提供了相应的代码实现来解决这两个问题。
摘要由CSDN通过智能技术生成

A. Sorting Parts

签到题

思路

n个数,分别将1~(n-1) 长度的前后缀进行排序,如果某次不是非降序就输出"YES",否则输出"NO"

就是因为前后缀长度从1开始,所以只要原始的数组里有一个数是不满足非降序的,那么在之后的某次排序中一定不满足非降序
eg: 2 1 4 5 6
排序,先是对 长度为1的前后缀排序,仍然是 2 1 4 5 6 不满足非降序

代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef int Bool;
typedef long long ll;
#define MS(a, b) memset(a, b, sizeof(a))
int compare(const void* a, const void* b);

ll s[N]; 
int main() {
	int T;
	scanf("%d", &T);
	while (T--) {
		int n = 0;
		MS(s, 0);
		scanf("%d", &n);
		for (int i = 0; i < n; i++) {
			scanf("%lld", &s[i]);
		}
		int flag = 0;
		for (int i = 1; i < n; i++) {
			if (s[i] < s[i - 1]) flag = 1;
		}
		if (flag) printf("YES\n");
		else printf("NO\n");
	}
	return 0;
}
int compare(const void* a, const void* b) {
	ElementType * s1 = (ElementType*)a;
	ElementType * s2 = (ElementType*)b;
	if (*s1 > *s2) return 1;
	else
	if (*s1 == *s2) return 0;
	else return -1;
}

C. Andrew and Stones

签到题…但是我还是没看懂

思 路

n堆石子,每堆ai个,选三个数 1 ≤ i < j < k ≤ n,并且 j 必须大于等于2
将j中石子,每次向 i 放一个 向k 放一个
问是否能把所有石子都移动到 第一堆和最后一堆里

分情况

  1. n == 3 ,中间如果是奇数就不能
  2. n为任意,中间全是1,不能移动石子,输出-1
  3. 满足情况的

所以直接在遍历的时候判断是不是全是1即可,
然后记录下最小的步数为,(s[i] + 1) / 2的和

代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<time.h>

typedef int Bool;
typedef long long ll;
typedef unsigned long long ull;

#define N 100000+5
#define MS(a, b) memset(a, b, sizeof(a))

/*应该是除了 n == 3 时中间的数是奇数,和任意n的所有中间数都小于2,之外的情况都可以*/
ll s[N], sum, ans;
int main() {
	int T, n;
	scanf("%d", &T);
	while (T--) {
		sum = 0;//记录总步数 (s[i] + 1) / 2 
		ans = 0;//判断是否全是 1  
		MS(s, 0);
		scanf("%d", &n);
		for (int i = 0; i < n; i++)
			scanf("%lld", &s[i]);
		for (int i = 1; i < n - 1; i++) {
			ans |= (s[i] > 1) ;
			sum += (s[i] + 1) / 2;
		}
		if (!ans || (n == 3 && s[1] % 2 == 1))	printf("-1\n");
		else printf("%lld\n", sum);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值