CCF 2021-09-2 non zero segment division

Keywords: CCF

Title Description

 

A1,A2,⋯,An   It's a   n   An array of natural numbers (non negative integers). We call it   Ai,⋯,Aj   Is a non-zero segment if and only if the following conditions are met at the same time:

  • 1≤i≤j≤n;
  • For any integer   k. If   i ≤ K ≤ j, then   Ak>0;
  • i=1   or   Ai−1=0;
  • j=n   or   Aj+1=0.

Here are some simple examples:

  • A=[3,1,2,0,0,2,0,4,5,0,2]   Medium   four   The non-zero segments are   [3,1,2],[2],[4,5]   and   [2];
  • A=[2,3,1,4,5]   have only   one   A non-zero segment;
  • A=[0,0,0]   Then there are no non-zero segments (i.e. the number of non-zero segments is)   0).

Now we can compare arrays   A   Do the following: select any positive integer   p. Then   A   All less than   p   All the numbers become   0 Try to choose a suitable one   p. Make array   A   The number of non-zero segments in reaches the maximum. If entered   A   The number of non-zero segments has reached the maximum, which can be taken   p=1, i.e. No   A   Make any changes.

Input format

Read in data from standard input.

The first line of input contains a positive integer   n.

The second line of input contains   n   A natural number separated by spaces   A1,A2,⋯,An.

Output format

Output to standard output.

Only one integer is output to represent the array   A   The maximum number of non-zero segments after operation.

Example 1 input

11
3 1 2 0 0 2 0 4 5 0 2

Sample 1 output

5

Example 1 explanation

p=2   When, A=[3,0,2,0,0,2,0,4,5,0,2], 5   The non-zero segments are   [3],[2],[2],[4,5]   and   [2]; At this time, the number of non-zero segments reaches the maximum.

Example 2 Input

14
5 1 20 10 10 10 10 15 10 20 1 5 10 15

Example 2 output

4

Example 2 explanation

p=12   When, a = [0,0,20,0,0,0,15,0,20,0,0,0,0,15], 4   The non-zero segments are   [20],[15],[20]   and   [15]; At this time, the number of non-zero segments reaches the maximum.

Example 3 input

3
1 0 0

Example 3 output

1

Example 3 explanation

p=1   When, A=[1,0,0], only   one   Non zero segments   [1] , the number of non-zero segments reaches the maximum.

Example 4 input

3
0 0 0

Example 4 output

0

Data

Example 4 explanation

whether   p   What is the value, A   None of them contain non-zero segments, so the number of non-zero segments is at most   0

Subtask

70%   The test data meet the requirements   n≤1000;

All test data meet   n≤5 ×, and array   A   No more than  .

problem analysis

70 code points (recursion + violence)

At the first glance, I saw the supplement of the problem scale. After simple calculation, I realized that it was impossible to use simulated violence to solve the problem, so I ran for 70 points at the beginning. I felt good before looking for P, and then... In short, the idea of 70 points is to recursively calculate the number of non-zero segments of a given sequence according to the meaning of the problem, and then violence every possible p value, Record and update max.

#include<iostream>

using namespace std;
int const N = 1000;

int a[N];
int feilingduan(int s,int e,int p){	
	if(s == e ){
		if(a[s] - p < 0)
			return 0;
		else{
			return 1;	
		}
	}else{
		int mid = (s + e)/2;
		if(a[mid] - p >= 0 && a[mid+1] - p >= 0){
			return feilingduan(s,mid,p) + feilingduan(mid+1,e,p) - 1;
		}else{
			return feilingduan(s,mid,p) + feilingduan(mid+1,e,p);
		}
	}
}

int main(){
	int n;
	cin >> n;
	int maxa = 0;
	for(int i = 0;i < n;i++){
		cin>>a[i];
		if(a[i] > maxa){
			maxa = a[i];
		}
	}
	int p = 1;
	int max = 0;
	for(p = 1;p <= maxa;p++ ){
		if(max < feilingduan(0,n-1,p) ){
			max = feilingduan(0,n-1,p);
		}
	}
	cout<<max; 
}
/*
110 + 022 l + r
111 + 022 l + r
110 + 200 l + r
111 + 222 l + r - 1 
*/

100 point code (recursion + violence + three points)

The next step is the optimization on this basis. At first, I directly thought of the idea similar to dichotomy. Later, after thinking, I found that it could not be realized, because it was neither monotonous nor unipolar. I read it later Teacher's solution Only then did I know that there were three optimization ideas (although the teacher said it was lucky, it was still 100).

#include<iostream>//42min

using namespace std;
int const N = 5*100000;
int a[N];
int n;

int feilingduan(int s,int e,int p){	
	if(s == e ){
		if(a[s] - p < 0)
			return 0;
		else{
			return 1;	
		}
	}else{
		int mid = (s + e)/2;
		if(a[mid] - p >= 0 && a[mid+1] - p >= 0){
			return feilingduan(s,mid,p) + feilingduan(mid+1,e,p) - 1;
		}else{
			return feilingduan(s,mid,p) + feilingduan(mid+1,e,p);
		}
	}
}

int findmax(int sp,int ep){
	while(ep - sp > 4){
		int ssp = sp + (ep - sp + 1) / 3;
		int eep = ep - (ep - sp + 1) / 3;
		if(feilingduan(0,n-1,ssp) < feilingduan(0,n-1,eep))
			sp = ssp;
		else
			ep = eep;
	}
	int max = 0;
	for(int i = sp;i <= ep ;i++ ){
		if(max < feilingduan(0,n-1,i) ){
				max = feilingduan(0,n-1,i);
		}
	}
	return max;
}

int main(){
	
	cin >> n;
	int maxa = 0;
	for(int i = 0;i < n;i++){
		cin>>a[i];
		if(a[i] > maxa){
			maxa = a[i];
		}
	}	
	if(n <= 1000){
		int p = 1;
		int max = 0;
		for(p = 1;p <= maxa;p++ ){
			if(max < feilingduan(0,n-1,p) ){
				max = feilingduan(0,n-1,p);
			}
		}
		cout<<max;
	}
	else{
		cout<<findmax(1,maxa); 
	}
}
/*
110 + 022 l + r
111 + 022 l + r
110 + 200 l + r
111 + 222 l + r - 1 
*/

100 point code (index)

According to the teacher's problem solution, I learned the teacher's index code. However, I feel that it is easy to confuse whether the book array storage is set to 0 and 1 is set to 0, so I changed it and used the array to represent its outline. For example, 1 is non-0 and 0 is < p, but the conditions for changing the segmentation have not changed.

#include<iostream>//42min + 30min
#include<vector>
using namespace std;

int const N = 5*100000; 
int a[N];//Store each specific data 
int range[N];//Stored as abstract 0 1 0 represents < p 1 represents > = P  
vector<int>v[10000+1];//Each v[i] stores the position corresponding to all I 

int main(){
	int n;
	int last = 1;//Last is the score of the last stroke. When p = 0, last = 1  
	cin >> n;
	int maxa = 0;
	for(int i = 1;i <= n;i++){
		cin >> a[i];
		v[a[i]].push_back(i);
		if(a[i] > maxa){
			maxa = a[i];
		}
		range[i] = 1;
	}
	range[0] = 0;
	range[n + 1] = 0;	
	
	int max = 0;
	for(int p = 0;p <= maxa;p++){
		if(v[p].size() != 0){//Mark the number less than p as 0 in the range array, which is equivalent to changing the condition to < = p to 1. If the problem is not investigated, p has little impact
			int t = last;
			for(int i = 0;i < v[p].size();i++){
				range[ v[p][i] ]= 0;//Set all in v[p] to 0 
				if(range[ v[p][i] - 1] == 0 && range[ v[p][i] + 1] == 0){
					t--;
				}else if(range[ v[p][i] - 1] == 1 && range[ v[p][i] + 1] == 1){
					t++;
				}
			}
			if(max < last)	max = last;
			if(max < t)		max = t;
			last = t;
		}
	}	
	cout<<max;
}

/*
110 + 022 l + r
111 + 022 l + r
110 + 200 l + r
111 + 222 l + r - 1 
*/

/*
01111110   p = 0 
01010110   p = 1
*/

Posted by davo666 on Sun, 10 Oct 2021 05:29:58 -0700