栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

CCF202109-2非零段划分(c++)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

CCF202109-2非零段划分(c++)

题目:

 解法: 解法一:(暴力求解法,70分)

暴力求解,就不给解释了,想看的稍微看一看即可。

#include 
using namespace std;
int max(int a[],int n) {
	int x=0;
	for(int j=0; j=x) x=a[j];
	}
	return x;
}
bool quanling(int a[],int n) {
	for(int i=0; i>n;
	int a[n];
	for(int i=0; i>a[i];
	int Max=max(a,n);
	if(quanling(a,n)) {
		cout<<0;
	} else {
		int count=0;
		for(int p=1; p<=Max; p++) {
			int temp=0;
			for(int j=0; j=1) {
					if(a[j]=p) temp++;
					else if(a[j]=p&&a[j+1]=p&&a[j+1]>=p) continue;
				} else {
					if(a[j]=p) temp++;
					else if(a[j]>=p) temp++;
				}

			}
			if(temp>=count) count=temp;
		}
		cout< 
解法二:(索引法,100分) 

首先要找到一个向量,这个向量可以存储数组a中值的位置。即向量v[i]中存储的便是i在数组a中的位置。此时向量v可以看成数组a中每个值的索引。然后还要找到一个数组,此数组与数组a的值一一对应用作标记,即a[i]的值一旦被置为0,此数组[i]则被置为1.

开始时,要在数组a前后两端置0,并且对标记数组进行初始化。程序中有一last(上一次划分的段数)。取p为0到maxa(数组a的最大值),每个p则代表小于等于p的值置0。找到值为p的位置将标记数组记为1,当此位置左右均已置为0时划分段树减一,当此位置左右均不为0时则划分段加一。然后对目前结果,上一次划分段数last以及此次划分段数取最大值记为目前结果。最后将此次划分段数记为上一次划分段数last。

#include 
#include 
#include 
using namespace std;
const int N = 500000;
const int M = 10000;
int a, book[N + 2];
vector  v[M + 1];
int main() {    //索引法
	int n, maxa = 0;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a;
		maxa = max(maxa, a);
		v[a].push_back(i);   //v[a]中存储的是a在数组a中的位置
	}
	int ans = 0;   //结果,最大段数
	if (v[0].size() != n) {    //如果数组a并非全0
		memset(book, 0, sizeof book);   //将book数组全部置零
		book[0] = book[n + 1] = 1;//数组两端已经置零则被标记为1
		int last = 1;
		for (int p = 0; p <= maxa; p++) {
			if (v[p].size() != 0) {
				int tem = last;
				for (int i = 0; i < (int)v[p].size(); i++) {
					book[v[p][i]] = 1;
					if (book[v[p][i] - 1] && book[v[p][i] + 1]) tem--;
					else if (book[v[p][i] - 1] == 0 && book[v[p][i] + 1] == 0) tem++;
				}
				ans = max(ans, max(last, tem));
				last = tem;
			}

		}

	}
	//数组a全0
	cout << ans;
	return 0;
}

顺手给出一个关于vector的网址:

https://blog.csdn.net/whu_little_hack/article/details/112980332?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163790238216780271985216%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=163790238216780271985216&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-112980332.pc_search_es_clickV2&utm_term=vector%E5%AE%B9%E5%99%A8&spm=1018.2226.3001.4187

解法三:(差分法,100分)

用差分法可以借助岛屿情况来分析。p足够大,所有的数(岛屿)被海水淹没,只有0个岛屿(划分段)。当海平面逐渐下降,岛屿数量出现变化。每当出现一个凸峰,岛屿数加一,每当出现一个凹谷,原本相邻的两个岛屿就被这个凹谷连在了一起,岛屿数减一。

#include 
#include 
using namespace std;
const int N=500000;
const int M=10000;
int a[N+2],d[M+1];
int main() {  //差分法
	int n;
	cin>>n;
	for(int i=1; i<=n; i++) cin>>a[i];
	a[0]=a[n+1]=0;
	n=unique(a,a+n+2)-a-1;    //最后一位坐标 
	memset(d,0,sizeof d);
	for(int i=1; ia[i]&&a[i]=1; i--) {
		sum+=d[i];
		ans=max(ans,sum);
	}
	cout<

总的来说,差分法就是先消去相邻的重复元素,再从unique后的数组第一位到最后一位,依次比较数字与相邻数的大小,并对d操作。(解释一下下:如果此时是从d[i]+d[i+1]+........  则表示海平面为i时的岛屿数量,即p=i时的划分段数。)

这里说明一下unique,unique()函数是用来去除相邻重复的元素,返回的结果为去除相邻重复元素后的数组(将去除相邻元素后的数组放在新数组的前面部分,新数组的后面部分保持不变)

放个代码解释一下:

#include 
#include 
using namespace std;
int main() {
	int n;
	cin>>n;
	int a[n];
	for(int i=0; i>a[i];
	cout<<"原数组:"< 

运行情况:

还有一特殊情况(本人认为unique后数组最后几位0合归为一位):

 

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/604775.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号