(discretization) Luogu P1496 burning red cliff

Keywords: less

Luogu P1496 burning red cliff

First of all, this problem can be simulated. The simulation method needs some skills, but this paper talks about the discretization method, so the simulation method is ignored.

Algorithm analysis 1: first of all, if you ignore the ship position range of this problem (the ship position range of this problem reaches 10 ^ 9 and also contains negative numbers), and assume that the range is relatively small and does not contain positive numbers, then the solution of this problem is quite intuitive. You only need to use a tag array (bool array). When the array is initialized, all the elements are false. Then the main function will input the involved If the range is set to true, and the number of true is counted at last, it can play the role of de duplication. The code is as follows (for most input samples, the code will be out of bounds, so the code is only used to understand the algorithm, not easy to run!!!)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<stack>
#include<vector>
#define ll long long
using namespace std;
const int maxn=10000000;
bool vis[maxn];
int n;
int ans=0;
int main(){

  cin>>n;
  int xx,yy;
  for(int i=0;i<n;i++){
  	cin>>xx>>yy;
  	for(int j=xx;j<yy;j++) vis[j]=true;//Note that the interval should be left closed and right open, otherwise it will be counted as one more
	}
  
  for(int i=1;i<maxn;i++) if(vis[i]) ans++;
  
  cout<<ans;
  
  return 0;
}

Algorithm analysis 2: the above code obviously can't solve this problem, because the array can't be opened to 10 ^ 9 and negative subscript can't appear (although the negative subscript compiler won't report an error, or even calculate the correct result, but array overrun is not easy to try). However, we still hope to solve the problem by de duplication through tagging, so what can we do to solve the problem of insufficient array range?

By looking at the data range of the topic, we can see that although each ship may be far away, the total number of ships is very small. We can imagine as much as we like that although the Yangtze River is very long, if the boats on the Yangtze River are connected, the length is far less than the length of the Yangtze River. That is to say, if we really have a very long array with negative subscripts, and then on this basis, we really do it according to the above "algorithm analysis 1" method, then after storing the data, we will find that the elements in the array are extremely "sparse", and there may be several true only after a lot of false, so we waste a lot of space Between.

Back to the scene of the Yangtze River and the ships, if we want to measure the length of all the ships on the Yangtze River (as this topic is not repeated), then we don't have to or can't really send a person to find the tail of the Yangtze River from the head of the Yangtze River, one meter to one meter. Instead, we can ask each ship to send a "signal" to itself, which contains the ship's head and tail coordinates. Then we only need a very small bool array (the length will not exceed twice the number of ships, because one ship has two coordinates), which can store these signals. At the same time, we can count the relative position of each ship. For example, the true coordinates of a ship may be (2000045000), that is, 20000 at the bow and 45000 at the stern, but since 20000 is the second in all the coordinates, and 45000 is the fourth, then our bool array can only set between 2 and 4 as true. In addition, in order to prevent the loss of the original coordinate data (2000045000), we can set an array p for discretization, set p[2] to 20000 and p[4] to 45000. Considering the data range of the coordinates, the element of array p set to long long is completely saved.

The specific algorithm is shown in the figure, assuming that the input (different from the example on the question) is
3
-1 1
2 9
7 11

The AC code is as follows:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<set>
#define ll long long
using namespace std;
const int maxn=20050;
bool vis[maxn*2];
int n;
ll ans=0;
ll l[maxn];                         //Save the left coordinates of each ship, discretize them, and then save them back to l 
ll r[maxn];                         //Same as l, but save the coordinates on the right 
set<int> setti;                     //With set, the sorting can be completed at the same time when reading in 
ll p[maxn*2];                       //p array in algorithm analysis 2
int len;                            //Length of p array 
int erfen(int x,int y,ll v){
	int m;
	while(x<y){
		m=x+(y-x)/2;
		if(p[m]==v) return m;
		else if(p[m]>v) y=m;
		else x=m+1;
	}
	return -1;
}

int main(){
  
  cin>>n;
  for(int i=0;i<n;i++){             //Simulate according to the above algorithm analysis 
  	cin>>l[i];
  	cin>>r[i];
  	setti.insert(l[i]);
  	setti.insert(r[i]);
	}
	for(set<int>::iterator it=setti.begin();it!=setti.end();it++,len++)
	  p[len]=*it;                     //For the traversal of set, please refer to Chapter 5 of purple book 
	
	for(int i=0;i<n;i++){             //Coordinates after discretization 
		l[i]=erfen(0,len,l[i]);
		r[i]=erfen(0,len,r[i]);
		for(int j=l[i];j<r[i];j++) vis[j]=true;
	}
	int pos=0;                        //Next, find the continuous true 
	while(pos<n*2){                   //Notice that the upper bound here is n*2 
	  if(vis[pos]==0) pos++;
		else{
		  int k=pos;
		  while(vis[k]) k++;
		  ans+=p[k]-p[pos];
		  pos=k;
	  }
	}
  
  cout<<ans;
  
  return 0;
}

When the code is read in, set is used. In the code implementation, I made a mistake. When I wrote the code, I mistakenly thought that set insertion can be used without sorting, so the algorithm complexity must be lower than adding l[p] and r[p] to the p array and then sorting. After consulting the data, I found that the algorithm complexity of the former is indeed lower than that of the latter, but it is different from my original estimation. In my own code, the set in STL is essentially a red black tree. The algorithm complexity of inserting elements is O(lgn), and N times of inserting is lg1+lg2+lg3 + +LG n = LG (n!), the latter is nlgn=lg(n^n). (in addition, both codes have the process of moving data into the p array). The code for the latter case is as follows:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<set>
#define ll long long
using namespace std;
const int maxn=20050;
bool vis[maxn*2];
int n;
ll ans=0;
ll l[maxn];                         //Save the left coordinates of each ship, discretize them, and then save them back to l 
ll r[maxn];                         //Same as l, but save the coordinates on the right 
//Set < int > setti; / / with set, you can finish sorting at the same time when reading in 
ll p[maxn*2];                       //p array in algorithm analysis 2
int len;                            //Length of p array 
int erfen(int x,int y,ll v){
	int m;
	while(x<y){
		m=x+(y-x)/2;
		if(p[m]==v) return m;
		else if(p[m]>v) y=m;
		else x=m+1;
	}
	return -1;
}

int main(){

  cin>>n;
  for(int i=0;i<n;i++){             //Simulate according to the above algorithm analysis 
  	cin>>l[i];
  	cin>>r[i];
  	//setti.insert(l[i]);
  	//setti.insert(r[i]);
  	p[len++]=l[i];
  	p[len++]=r[i];
	}
	//for(set<int>::iterator it=setti.begin();it!=setti.end();it++,len++)
	//  For traversal of P [len] = * it; / / set, please refer to Chapter 5 of purple book 
	
	sort(p,p+len);

	for(int i=0;i<n;i++){             //Coordinates after discretization 
		l[i]=erfen(0,len,l[i]);
		r[i]=erfen(0,len,r[i]);
		for(int j=l[i];j<r[i];j++) vis[j]=true;
	}
	int pos=0;                        //Next, find the continuous true 
	while(pos<n*2){                   //Notice that the upper bound here is n*2 
	  if(vis[pos]==0) pos++;
		else{
		  int k=pos;
		  while(vis[k]) k++;
		  ans+=p[k]-p[pos];
		  pos=k;
	  }
	}
  
  cout<<ans;
  
  return 0;
}

Comparison of the results in two cases: set instead of sort and sort:
Former (set):

The latter (sort):

The remaining problem is why the first speed is less than the second when Chen 8. I downloaded the data of Chen 8, but there are more than 10000 points, which is not easy to analyze.

57 original articles published, praised 7, visited 1289
Private letter follow

Posted by seikan on Tue, 21 Jan 2020 04:25:29 -0800