AGC008

AGC008

B

题目大意

给出一个序列,一开始全是白色,一次操作可以染黑或染白一段长度为 K 的区间,要让最后序列中黑色格子上数的和最大,求这个最大值。

解题思路

考虑找结论

发现我们一定要尽可能地把正数涂黑,负数涂白,由于对操作次数没有限制,因此对一个正数我们只要将其放在区间首位涂黑,再把后面的数涂白即可实现单独将其涂黑。

但是我们发现如果这么做最后的 K 个数就无法实现,同理,如果逆转从后往前涂那么前 K 个数就无法实现。

考虑一段从前往后,一段从后往前,中间就会有 K 个数无法实现,而其他正数都能取到

因此我们可以枚举这个无法实现的区间,如果它求和大于 0 就加上,否则不加,然后将剩下的所有正数求和加上。

代码上,我们可以维护两个前缀和,一个是序列的前缀和 s1,一个是正数的前缀和 s2

答案即为:

maxi=1nk+1(s2[i1]+s2[n]s2[i+k1]+max(0,s1[i+k1]s1[i1]))

代码

#include<bits/stdc++.h>
#define endl "\n"
#define ll long long
using namespace std;

const int N = 1e5 + 10;

int n, k;
ll s1[N], s2[N], ans;

int main()
{
	ios :: sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n >> k;
	for (int i = 1; i <= n; i++)
	{
		cin >> s1[i];
		s2[i] = s2[i - 1];
		if (s1[i] > 0)
		{
			s2[i] += s1[i];
		}
		s1[i] += s1[i - 1];
	}
	for (int i = 1; i <= n - k + 1; i++)
	{
		ans = max(ans, s2[i - 1] + s2[n] - s2[i + k - 1] + max(0ll, s1[i + k - 1] - s1[i - 1]));
	}
	cout << ans << endl;
	return 0;
}

D

题目大意

构造一个序列 a,使得:

  1. a 的长度为 N2,并且满足数字 1,2,,N 都各出现恰好 N 次。

  2. 对于 1iN,数字 ia 中第 i 次出现的位置是 Xi

解题思路

考虑贪心

题意即为:对于 1iN,位置 Xi 上的数为 i,前面有 i1i,后面有 ni 个。

考虑先满足前一个条件,我们可以对 Xi 从小到大排序,然后放在 Xi 前面空位即可,放不下就必定无解。

但是我们为了顾及后面一个条件,那么就需要尽可能少地占用后面的空位,因此我们填数时在最前面的空位一定是最优的。

于是后面一个条件只需从大到小遍历,找后面的空位放即可(不一定要选取最后面,但为了编写方便,不妨就选最后的空位)。

代码

#include<bits/stdc++.h>
#define endl "\n"
using namespace std;

const int N = 510;

struct node
{
	int id, x;
} b[N];

int n;
int a[N * N];

bool cmp(node x, node y)
{
	return x.x < y.x;
}

int main()
{
	ios :: sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> b[i].x;
		a[b[i].x] = i;
		b[i].id = i;
	}
	sort(b + 1, b + n + 1, cmp);
	for (int i = 1, p = 1; i <= n; i++)
	{
		for (int j = 1; j < b[i].id; j++)
		{
			while (p <= b[i].x && a[p] != 0)
			{
				p++;
			}
			if (p > b[i].x)
			{
				cout << "No" << endl;
				return 0;
			}
			a[p++] = b[i].id;
		}
	}
	for (int i = n, p = n * n; i >= 1; i--)
	{
		for (int j = b[i].id + 1; j <= n; j++)
		{
			while (p >= b[i].x && a[p] != 0)
			{
				p--;
			}
			if (p < b[i].x)
			{
				cout << "No" << endl;
				return 0;
			}
			a[p--] = b[i].id;
		}
	}
	cout << "Yes" << endl;
	for (int i = 1; i <= n * n; i++)
	{
		cout << a[i] << " ";
	}
	return 0;
}
posted @   I_LOVE_MATH  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示