暴力求解,就不给解释了,想看的稍微看一看即可。
#includeusing 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; i a[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合归为一位):



