洛谷5月月赛Ⅱ 比赛总结

本文主要介绍了两个算法问题的解决方案。第一个问题是关于寻找特定数值是否存在于一个给定长度的最大和最小等差数列之间。第二个问题涉及使用栈来处理区间覆盖,通过判断新区间是否能合并到已有的区间栈中,实现有效的区间合并和计算。这两个问题都涉及到基础的数据结构和算法应用。

因为对树的知识尚不熟悉, 所以只完成了A与B题。

A.凑数

在这里插入图片描述
这道题算是比较简单的, 通过输入的n去计算最大等差数列和最小等差数列, 如果所求数在这两个值之间, 则必然可求


#include <stdio.h>

_Bool Sum(unsigned long long n,unsigned long  long k,unsigned long long s);
int main(void)
{
	long t;
	unsigned long long n, k, s;
	scanf("%ld", &t);
	for (long i = 0; i < t; i++)
	{
		scanf("%llu %llu %llu", &n, &k, &s);
		if (Sum(n, k, s))
			puts("Yes");
		else
			puts("No");
	}
	
	return 0;
}

_Bool Sum(unsigned long long n,unsigned long long k,unsigned long long s)
{
	unsigned long long minSum = 0;
	unsigned long long  maxSum = 0;
	
	minSum = (k * k + k)/ 2;
	if (minSum > s)
		return 0;
	maxSum = (n + n - k + 1) * k / 2;
	if (minSum <= s && maxSum >= s)
		return 1;
	else
		return 0;

}

B. clear up
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
通过建立一个栈来不断存入弹出,
分三种情况

  1. 新入栈的被之前的盖住, 那就拒绝其入栈, continue
  2. 新入栈的可以盖住前面的, 那就不弹出上一个元素, 直到有一个不会被盖住
  3. 两个有区间交, 进行合并
  4. 两个无区间交, 入栈

三人组总有第四个人, 不是么

#include <stdio.h>

#define N 1000000

long long stack[N][3] = { 0 };


long long Marge(long long* restrict num, const long long  n);
int main(void)
{
	long long int retnum;
	long long  n;
	long long num[N];
	scanf("%lld", &n);
	for (long long i = 0; i < n; i++)
		scanf("%lld", &num[i]);
	retnum = Marge(num, n);

	printf("%lld", retnum);
	return 0;
}

long long Marge(long long* restrict num, const long  long n)
{
	
	long long val;
	long long stackPoint = 0;
	long long i;
	for (i = 0; i < n; i++)
	{
		if (num[i] == 0)
			continue;
		if (stackPoint > 0 && stack[stackPoint - 1][1] >= i + num[i])
			continue;
		stack[stackPoint][0] = i - num[i];
		stack[stackPoint][1] = i + num[i];
		stack[stackPoint][2] = num[i];
		while (stackPoint > 0 && stack[stackPoint][0] <= stack[stackPoint - 1][0])
		{
			stack[stackPoint - 1][0] = stack[stackPoint][0];
			stack[stackPoint - 1][1] = stack[stackPoint][1];
			stack[stackPoint - 1][2] = stack[stackPoint][2];
			stackPoint--;
		}
		while (stackPoint > 0 && stack[stackPoint - 1][1] >= stack[stackPoint][0])
		{
			long long temp = stack[stackPoint][1] - stack[stackPoint - 1][0];
			temp += temp & 1 ? 1 : 0;
		//	printf("%lld\n", temp);
			stack[stackPoint - 1][2] = temp  / 2;
			stack[stackPoint - 1][1] = stack[stackPoint][1];
			stackPoint--;
		}
		stackPoint++;
	}
	for (i = 0, val = 0; i < stackPoint; i++)
	{
//		printf("%lld %lld %lld\n", stack[i][0], stack[i][1], stack[i][2]);
		val += stack[i][2];
	}
	return val;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值