Sequence 2023牛客暑期多校训练营6 E

登录---专业IT笔试面试备考平台_牛客网

题目大意:有一长度为n的数组a,有q次询问,每次要求将[l,r]的区间分成k个连续区间,满足每个区间和都是偶数,能满足要求就输出YES

1<=n,q<=1e5;0<=ai<=1e10;1<=l<=r<n;1<=k<=1e5

思路:要想和为偶数,那么奇数的数量必须是偶数个,所以我们把数组中的数都变成%2后的结果,也就是整个数组只有0和1构成,每个0可以作为一个合法的区间,而每个1必须要和其相邻的一个1组合才能构成一个最小的合法区间,而如果一个1和其相邻的一个1组成一个区间,那这两个1中间的0都不能作为合法的区间。

所以我们要分两种情况讨论,一种是数组中从左往右第二个1和第一个1组合,另一种是第二个和第三个1组合,然后分别对合法区间数求前缀和,每个0的贡献都是1,每个含有两个1的区间,整个区间贡献是1,例如对于0 0 1 0 0 1 0 0 1 0 0 1 0这个数组,第一个前缀和数组sum1求出来的是1 2 3 3 3 3 4 5 6 6 6 6 7,第二个数组sum2是0 0 0 1 2 3 3 3 3 4 5 6 6,另外,还要特判一下每个区间内1的数量是否是偶数,如果是奇数就可以直接输出no了。

对于其他情况,我们要看每个询问的区间适用于哪个数组,如果a[r]是1,那么哪个数组的sum[r]=sum[r-1],说明哪个数组是合法的,如果a[r]是0,那么就看哪个sum[r]!=sum[r-1],不等的那个数组提供贡献

cpp 复制代码
#include<bits/stdc++.h>
//#include<__msvc_all_public_headers.hpp>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
const ll MOD = 998244353;
ll a[N];
ll sum[N];
ll sum2[N];
ll sum3[N];
void solve()
{
	int n, q;
	cin >> n >> q;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		a[i] %= 2;//将数组按奇偶转换成1和0
		sum[i] = sum[i - 1] + a[i];//统计区间奇偶性
        sum2[i] = sum3[i] = 0;
	}
	int flag = 0;
	for (int i = 1; i <= n; i++)
	{
		if (!a[i])
		{
			if(!flag)
				sum2[i] = 1;//在两个1中间以外的0贡献为1
		}
		else
		{
			if (!flag)
			{
				flag = i;//记录上一个1的位置
			}
			else
			{
				sum2[flag]++;//上一个1到这一个1之间总共贡献1
				flag = 0;
			}
		}	
	}
	if (flag)//末尾没有匹配的1要+1贡献与前面的0区分开
		sum2[flag]++;
	flag = 0;
    int fi=0;
	for (int i = 1; i <= n; i++)
	{
		if (!a[i])
		{
            if(!fi)//在遇到第一个1之前不记录贡献
                continue;
			if (!flag)
				sum3[i] = 1;
		}
		else
		{
            if(!fi)
            {
                fi=i;//遇到第一个1之后,后面的统计与上一个数组相同
                continue;
            }
			if (!flag)
			{
				flag = i;
			}
			else
			{
				sum3[flag]++;
				flag = 0;
			}
		}
	}
	if (flag)
		sum3[flag]++;
	for (int i = 2; i <= n; i++)
	{//求前缀和得到区间内的合法区间数
		sum2[i] = sum2[i - 1] + sum2[i];
		sum3[i] = sum3[i - 1] + sum3[i];
	}
	for (int i = 1; i <= q; i++)
	{
		int l, r, k;
		cin >> l >> r >> k;
		if ((sum[r] - sum[l - 1]) % 2!=0)
		{
			cout << "NO" << endl;
			continue;
		}
		ll ans3 = sum3[r] - sum3[l - 1];
		ll ans2 = sum2[r] - sum2[l - 1];
		if (a[r] == 1)
		{//右端点是1,哪个数组r=r-1就说明哪个合法
			if (sum2[r] == sum2[r - 1])
			{
				cout << (ans2 >= k ? "YES" : "NO") << endl;
			}
			else
			{
				cout << (ans3 >= k ? "YES" : "NO") << endl;
			}
		}
		else
		{//右端点是0,哪个数组r!=r-1就说明哪个合法
			if (sum2[r] != sum2[r - 1])
			{
				cout << (ans2 >= k ? "YES" : "NO") << endl;
			}
			else
			{
				cout << (ans3 >= k ? "YES" : "NO") << endl;
			}
		}
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}
相关推荐
武子康7 分钟前
大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和
大数据·人工智能·学习·算法·机器学习·数据挖掘
passer__jw76735 分钟前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
Ocean☾42 分钟前
前端基础-html-注册界面
前端·算法·html
顶呱呱程序1 小时前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
爱吃生蚝的于勒1 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~1 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
王哈哈^_^2 小时前
【数据集】【YOLO】【VOC】目标检测数据集,查找数据集,yolo目标检测算法详细实战训练步骤!
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·pyqt
星沁城2 小时前
240. 搜索二维矩阵 II
java·线性代数·算法·leetcode·矩阵
脉牛杂德2 小时前
多项式加法——C语言
数据结构·c++·算法
legend_jz2 小时前
STL--哈希
c++·算法·哈希算法