2019年第十届蓝桥杯(C++)省赛J题

2019年第十届蓝桥杯(C++)省赛J题

灵能传输

1
嗯emmm,这个题目可以将蓝桥杯更名为阅读理解杯嘛=-=我把题目差点理解错了。。。???为什么不早点让我顿悟!!为什么两组形式化格式不一起给出呢??真心是阅读理解杯了。真的哭啊=-=看了yxc的视频=-=有点头绪=-=不然我自己会傻乎乎的模拟

给出没有代表性的样例:
【样例输入】
3
3
5 -2 3
4
0 0 0 0
3
1 2 3
【样例输出】
3
0
3
【样例说明】
对于第一组询问:
对 2 号高阶圣堂武士进行传输操作后 a 1 = 3,a 2 = 2,a 3 = 1。答案为 3。
对于第二组询问:
这一组高阶圣堂武士拥有的灵能都正好可以让他们达到最佳战斗状态。
【样例输入】
3
4
-1 -2 -3 7
4
2 3 4 -8
5
-1 -1 6 -1 -1
【样例输出】
5
7
4

如果我这道题碰上比赛的话肯定会毁终身的emmm

这道题大概就是一个处理前缀和和序列之间的题目+一点贪心把。想清楚了其实很简单啊哈哈哈

我们可以进行少部分模拟。
2
我们模拟一下把ai分给旁边两个人的情况,然后发现可以求前缀和耶,棒!!
于是我们发现,其实就是交换前缀和的问题了。。
根据题目要求i只能取到2~n-1的部分
所以我们交换的范围就是s1~s(n-1)
也就是sn不可以交换(它是如来,稳定不动)
那我们再来个特殊的,不怕麻烦(s0 = 0)
现在变成了s0, sn不允许交换,其他的任意交换。
我们要使得si - s(i - 1)的最大值最小

当我们不知道s0和sn大小的情况下(sn可能为负)
我们先来个极端特殊情况,假设s0是最小值,sn是最大值
那我们直接sort就可以直接得到答案。
那么一般情况是我们先从s0走到最小值,从最小值走到最大值,再从最大值走到sn(注意每个数只能经过一次)
形象的图形:
3
我们要满足每个数都要经过并且只能经过一次的要求,那我们贪心的策略就是隔点跳(可举例这是获得差值最小的策略)
那我们在处理隔点跳的时候写程序可能需要存在判别是否为奇数和偶数的情况
小技巧:开一个vis数组记录
那我们储存新的序列的时候从s0到最小值用left记录从左往右,最大值到sn就是用right记录从右往左,然后中间的值就用vis把没处理的数字保存起来就行
然后维护最大值就行嘻嘻。
对了,我们不知道s0和sn的大小情况,如果s0 > sn的话就交换一下就可以啦,可以省下一半的代码,需要跟我们上面的一般条件符合嘛=-=如果s0>sn的话,就是从s0到最大值,最大值到最小值,最小值到sn,是和上面情况是对称的,所以交换一下更方便~~

上代码啦~哇好晚了,我就先去睡觉啦,明早起来补题目

#include <bits/stdc++.h>
#define mst(a, n) memset(a, n, sizeof(a))
using namespace std;
typedef long long ll;
const int N = 3e5 + 10;

int n;
ll s[N], a[N];
bool vis[N];
ll ans = 0;

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		mst(a, 0);
		mst(s, 0);
		mst(vis, 0);
		ans = 0;
		cin >> n;
		s[0] = 0;
		for (int i = 1; i <= n; i++)
		{
			scanf ("%lld", &s[i]);
			s[i] += s[i - 1];
		}
		ll s0 = s[0], sn = s[n];
		if (s0 > sn)
		{
			swap(s0, sn);
		}
		sort(s, s + n + 1);
		for (int i = 0; i <= n; i++)
		{
			if (s[i] == s0)
			{
				s0 = i;
				break;
			}
		}
		for (int i = 0; i <= n; i++)
		{
			if (s[i] == sn)
			{
				sn = i;
				break;
			}
		}
		int l = 0, r = n;
		for (int i = s0; i >= 0; i -= 2)
		{
			a[l++] = s[i];
			vis[i] = 1;
		}
		for (int i = sn; i <= n; i += 2)
		{
			a[r--] = s[i];
			vis[i] = 1;
		}
		for (int i = 0; i <= n; i++)
		{
			if (!vis[i])
			{
				a[l++] = s[i];
			}
		}
		for (int i = 1; i <= n; i++)
		{
			ans = max(ans, abs(a[i] - a[i - 1]));
		}
		cout << ans << endl;
	}
	return 0;
}
发布了53 篇原创文章 · 获赞 2 · 访问量 1357

猜你喜欢

转载自blog.csdn.net/qq_44624316/article/details/104547563