csp真题 202109-2非零段划分C++代码(100分)
試題編號: 202109-2
試題名稱: 非零段劃分
時間限制: 1.0s
內存限制: 512.0MB
樣例1輸入
11 3 1 2 0 0 2 0 4 5 0 2樣例1輸出
5樣例1解釋
p=2時,A=[3,0,2,0,0,2,0,4,5,0,2],5個非零段依次為[3]、[2]、[2]、[4、5]和[2];此時非零段個數達到最大。
樣例2輸入
14 5 1 20 10 10 10 10 15 10 20 1 5 10 15樣例2輸出
4樣例2解釋
p=12時,A=[0,0,20,0,0,0,0,15,0,20,0,0,0,15],4個非零段依次為[20]、[15]、[20]和[15];此時非零段個數達到最大。
樣例3輸入
3 1 0 0樣例3輸出
1樣例3解釋
p=1時,A=[1,0,0],此時僅有1個非零段[1],非零段個數達到最大。
樣例4輸入
3 0 0 0樣例4輸出
0樣例4解釋
無論p取何值,A都不含有非零段,故非零段個數至多為0。
70分代碼及思路:
思路:
1.將所有數據存儲到一個數組A中,并記錄最大值max_A;
2.p從1開始遍歷到最大值max_A,記錄每一次p值下的非零段的個數最大值到數組max1中。
3.判斷非零段個數:遍歷數組,找到每一個不為0的值,如果該數前一個數為0或者該數是數組的第一個數,非零段個數加1。
4.遍歷數組max1,輸出最大值。
分析:
該方法屬于常規思路,比較簡單,無任何算法優化,有很多循環遍歷,且有雙層循環,由題目給出的數據范圍,在雙層循環中,循環次數有可能達到10^9,顯然會超時。
提交結果如下:
如果要拿到滿分,那么用常規的思路邏輯肯定不行,必須要做一定的優化處理,在參考b站視頻教程后整理如下:
1.讀入數組時插入set,對數組進行去重和排序,(方便p值的選取)。
2.利用向量vector,將set集合中每個元素出現的位置存儲在同一個vector向量中。
3.統計初始的非零段個數作為參考值。
(與前一種方法有點區別,在數組開頭和最后加0,只需判斷當前數不為0并且前一位數為0,非零段個數加1即可)
4.p依次從set中取值(從小到大)(如果值為0,跳過),依據位置向量獲得每個值在數組A中的位置。
將對應位置的值賦值為0
如果該位置的前后的值都大于0,則非零段數加1;
如果該位置的前后的值都等于0,則非零段數減1;
其他情況下非零段個數不變。
更新非零段的最大值。
該方法的優點在于:
通過向量對應的位置坐標,判斷坐標位置前后元素的值進行判斷即可,不必在每一個p值下都對數組進行循環遍歷,降低了時間復雜度。
此方法思路來源b站,可參考b站視頻內容
滿分代碼:
#include <bits/stdc++.h> using namespace std;int A[500002]= {0}; vector<int> Vector[10001]; set<int> Set;int main() {int n;cin>>n;for(int i=1; i<=n; i++) {cin>>A[i];Set.insert(A[i]);Vector[A[i]].push_back(i);}int number=0; //非零段個數for(int i=1; i<=n; i++) { //找出當前非零段的個數if((A[i]>0)&&(A[i-1]==0))number++;}int temp;int number_max; //非零段個數的最大值temp=number_max=number;set<int>::iterator p=Set.begin();//用迭代器來訪問set集合//p的值從集合開始遍歷if(*p==0) //如果集合中的元素為0,則直接從下一個元素開始p++;for(p; p!=Set.end(); p++) {vector<int> &Vector1=Vector[*p]; //引用Vector[*p]為Vector1 for(int i=0; i<Vector1.size(); i++) { //集合中該元素出現的總次數int k=Vector1[i]; A[k]=0;if((A[k-1]!=0)&&(A[k+1]!=0))temp++;if((A[k-1]==0)&&(A[k+1]==0))temp--;}number_max=max(number_max,temp);}cout<<number_max<<endl;return 0;}提交結果如下:
總結
以上是生活随笔為你收集整理的csp真题 202109-2非零段划分C++代码(100分)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python提取qq群成员代码_Pyth
- 下一篇: 【若依框架】代码生成详细教程