# Algorithm analysis and design of Beihang 2020-C2

Posted by plaggypig on Thu, 10 Feb 2022 22:33:22 +0100

# Say at the beginning

This blog only provides learning materials and my personal review. In the process of learning algorithms, the code should be typed by myself. It is not convenient to copy and paste the code directly. Copy code without harm.

# preface

The original intention of writing this series of blogs is that the process of learning algorithms is a little rough, and the mastery of various algorithms is not very skilled. In addition, when reviewing, I suffer from the pain of not having the problems of previous years. In order to make progress in the algorithm for myself and my younger brothers and sisters, I opened a pit for level 20 algorithm analysis and design.
This update of c2 is more about the review of data structure and the basis of c language. There are not many algorithms involved. You can see how you master your knowledge.

# A I've been waiting for this moment for a long time

## Title Description

As we all know, all electronic devices will lose their function in Hogwarts. So as long as Alex opens this letter, he doesn't have to make a question.

He learned in the letter that he needed to buy a wizard's robe, an owl and a magic wand.

Alex walks into Ollivander's wand shop and is told "wand chooses Wizard"

Life is different. The wand will choose the right wizard according to one's courage, loyalty, wisdom and ambition

Ollivander easily found Alex's four attribute values a, B, C and D.

Label the wand and the requirements of each wand for its owner can also be summarized as these four attributes AI, Bi, CI and di
Alex hopes that he can get the magic wand that fits him the most, that is to minimize | a − Ai|+|b − Bi|+|c − Ci|+|d − Di |. Which wand should he buy?

By the way, the larger the label, the higher the price of the wand. Therefore, Alex hopes to give priority to the cheaper one.

## input

Five positive integers in the first line n,a,b,c,d
Second line n A positive integer A1,A2,⋯,An
Third line n A positive integer B1,B2,⋯,Bn
Fourth line n A positive integer C1,C2,⋯,Cn
The fifth line n A positive integer D1,D2,⋯,Dn
n≤1000, Attribute values are in [1,100] Range

## output

The output line represents the answer

## analysis

This topic can be said to be very simple. Put the code directly
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int A[1005];
int B[1005];
int C[1005];
int D[1005];
int main()
{
int n,a,b,c,d,i,result,temp,min=0x7fffffff;
char ch;
scanf("%d %d %d %d %d",&n,&a,&b,&c,&d);
for(i=1;i<=n;i++)
scanf("%d",&A[i]);
for(i=1;i<=n;i++)
scanf("%d",&B[i]);
for(i=1;i<=n;i++)
scanf("%d",&C[i]);
for(i=1;i<=n;i++)
scanf("%d",&D[i]);
for(i=1;i<=n;i++){
temp=abs(a-A[i])+abs(b-B[i])+abs(c-C[i])+abs(d-D[i]);
if(temp<min){
min=temp;
result=i;
}

}
printf("%d",result);
return 0;
}

# B Cartland number

## Title Description

Binary tree is an important data structure.

There are one kind of binary tree with one node, two kinds of binary tree with two nodes, and five kinds of binary tree with three nodes. The binary tree with n nodes is recorded as h(n), and h(n) is also called Cartland number.

Now, give multiple groups of data, and each group of data will give a positive integer n. For each set of data, please output the value of h(n).

## input

The first line is a positive integer T，Indicates the number of data groups.

next T Rows, one positive integer per row n.

## output

For each line of input, output h(n)Value of.

## analysis

This topic is still not difficult, simple recursion can be

Here is my own code
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
long long int h(int jie){
if(jie==1)
return 1;
else
return ((4*jie-2)*h(jie-1)/(jie+1));
}
int main()
{
int n,i,jie;
long long int result;
scanf("%d",&n);
while(n--){
scanf("%d",&jie);
result=h(jie);
printf("%lld\n",result);
}

return 0;
}

# C. bus sorting

## Title Description

Marvolo went out for a day on the national day, but unfortunately, the transportation he chose was the bus: because of the holiday trip, the car was overcrowded, and it was very difficult to move to the door and get off.

Marvolo thought: at which stop do you get off? It's disordered at the beginning. Can you first adjust it to be orderly on the bus (that is, monotonous and non descending), so that you don't have to rush forward when you get off? If you want to adjust, how many times should you adjust at least? Because there are many people in the car, it is stipulated that the order of two adjacent people can only be exchanged at one time.

In order to simplify the problem, you can think that there are n people on the bus, and the ith person needs to get off at the ai stop. The position of the person standing at the beginning is the door position.

Take chestnuts for example. If there are three people, they will get off at stops 3, 1 and 2 respectively. First let the first two people change the order into 1,3,2, and then let the second two people change the order into 1,2,3, so that they can be adjusted into order. At this time, the adjustment times are the least..

## input

The first line is a positive integer n，Indicates the number of people.

In the next line, there are n A positive integer, th i Number representation ai.

## output

Output an integer indicating the minimum number of exchanges.

5
1 3 4 5 2

3

## analysis

This topic is difficult and needs to be used mergesort Dichotomy algorithm.
But think carefully about the process of changing positions. In fact, it is very similar to the process of dichotomy. It may be easier to understand by looking at the specific code,
Here is my own code.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int a[200005];
int L[500005];
int R[500005];
long long int count;
void megre(int a[],int p,int q,int r) {
int n1, n2, i, j, k;
n1 = q - p + 1;
n2 = r - q;
for (i = 1; i <= n1; i++){
L[i] = a[p + i - 1];
}

for (j = 1; j <= n2; j++){
R[j] = a[q + j];
}

L[i]=0x7fffffff;
R[j]=0x7fffffff;
i = 1, j = 1;
for (k = p; k <= r; k++) {
if (L[i] <= R[j]){
a[k]=L[i];
i++;
}
else{
a[k] = R[j];
count+=n1-i+1;
j++;
}
}
}
void megre_sort(int a[], int p,int r) {
int q;
if (p < r){
q = (p + r) / 2;
megre_sort(a, p, q);
megre_sort(a, q + 1, r);
megre(a, p, q, r);
}
}
int main()
{
int n,i,jie;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
megre_sort(a,1,n);
printf("%lld",count);

return 0;
}

# D move questions

## Title Description

Marvolo won't have a problem, so he decided to move it. But he has a strange habit. On day k, he must move k questions, or he will strike on the spot.

Marvolo has now found a question bank. There are n games in total, and there are a certain number of questions in each game. But he is very picky. He can only move one day for each game, and he can only move the problems in one game every day, and then the game will be abandoned. For every game, he doesn't have to move all the questions.

So the question is, how many days will Marvolo work at most?

## input

In the first row, the number of one is n(1≤n≤106) ，Indicates how many games there are.

The second line, n Integer a1,a2,...,an(1≤ai≤109)，How many questions are there in each game.

## output

Output a line, Marvolo Maximum number of working days before strike.

4
3 1 4 1

3

## analysis

This topic is not difficult. The slightly complicated point is that the competition with the same number of questions needs to be judged.

The following is my own code for reference only.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
int a[1000005];
int use[1000005];
int cmp(const void * a,const void *b){
return *(int *)a - *(int *)b;
}
int search(int start,int k,int n){
int i;
for(i=start+1;i<=n;i++)
if(a[i]>=k&&use[i]==0){
use[i]=1;
return i;
}
return 0;

}
int main()
{
int n,i,type=0,k;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
qsort(a+1,n,sizeof(int),cmp);
k=0;
while(++k){
type=search(type,k,n);
if(type==0)
break;
}
printf("%d",k-1);
return 0;
}

# E largest subarray

## Title Description

Define the sum of an array and the largest continuous non empty subarray as the largest subarray of the array.

Give you an array and find the sum of its largest subarray.

## input

The number in the first row is the length of the array n(1≤n≤106)
The second line contains n Integer a1,a2,...,an(−109≤ai≤109)，Represents an array.

## output

Output one number per line and the sum of the largest subarray.

4
1 2 3 4

10

## analysis

This topic is the classic template problem of the largest subarray, introduction to the algorithm p40 There is a detailed explanation, you can learn.
The following is my own code for reference only.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
typedef struct node Node;
struct node{
int left;
int right;
long long int sum;
};
int a[1000005];
long long int max;
Node findcross(int a[],int low,int mid,int high){
long long int leftsum=-9223372036854775808,rightsum=-9223372036854775808,sum;
int i,j,maxleft,maxright;
Node res;
sum=0;
for(i=mid;i>=low;i--){
sum=sum+a[i];
if(sum>leftsum){
leftsum=sum;
maxleft=i;
}
}
sum=0;
for(j=mid+1;j<=high;j++){
sum=sum+a[j];
if(sum>rightsum){
rightsum=sum;
maxright=j;
}
}
res.left=maxleft;
res.right=maxright;
res.sum=leftsum+rightsum;
return	res;

}
Node findmaxsub(int a[],int low,int high){
int mid;
Node A,B,C,res;
long long int rightsum,leftsum,crosssum;
if(low==high){
res.left=low;res.right=high;res.sum=a[low];
return res;
}
else{
mid=(low+high)/2;
A=findmaxsub(a,low,mid);
B=findmaxsub(a,mid+1,high);
C=findcross(a,low,mid,high)	;
if(A.sum>=B.sum&&A.sum>=C.sum)
return	A;
else if(B.sum>=A.sum&&B.sum>=C.sum)
return	B;
else
return	C;
}
}
int main()
{
int n,i,type=0,k;
Node res;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
res=findmaxsub(a,1,n);
printf("%lld",res.sum);
return 0;
}

# F binary search++

## Title Description

Give an ordered array a with length n, and the ith element is ai.

Next, there are m queries. The format of each query is op x. If op=1, it means to ask where x first appears; If op=2, it means asking where x last appeared. If x never appears, output Not Found.

## input

The first line has two positive integers n,m.

Next line, total n A positive integer, separated by spaces, representing an array a. It is guaranteed that the order has been arranged from small to large.

next m Rows, two positive integers per row op x,The meaning is shown above.

## output

For each query operation, the query result is output, one line for each query operation.

5 4
1 2 2 3 4
1 2
2 2
1 3
1 5

2
3
4

## analysis

This topic and c1 The questions in have similarities. You can turn to them.
The following is my own code for reference only.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#include<math.h>
int shu[1000005][2];
int order[1000005];
int L[500005];
int R[500005];
int F[500005];
int Y[500005];
void megre(int shu[][2],int p,int q,int r) {
int n1, n2, i, j, k;
n1 = q - p + 1;
n2 = r - q;
for (i = 1; i <= n1; i++){
L[i] = shu[p + i - 1][0];
F[i]=shu[p+i-1][1];
}

for (j = 1; j <= n2; j++){
R[j] = shu[q + j][0];
Y[j]=shu[q+j][1];
}

L[i]=0x7fffffff;
R[j]=0x7fffffff;
i = 1, j = 1;
for (k = p; k <= r; k++) {
if (L[i] <= R[j]){
shu[k][0] = L[i];
shu[k][1]=F[i];
i++;
}
else{
shu[k][0] = R[j];
shu[k][1]=Y[j];
j++;
}
}
}
void megre_sort(int shu[][2], int p,int r) {
int q;
if (p < r){
q = (p + r) / 2;
megre_sort(shu, p, q);
megre_sort(shu, q + 1, r);
megre(shu, p, q, r);
}
}
void chack(int t,int n){
int low = 1;
int high = n ;
int mid,midnum;
while(low<= high){
mid = (low + high)/2;
midnum = shu[mid][0];
if(midnum<t)
low = mid + 1;
else if(midnum>t)
high = mid - 1;
else{
if(shu[mid-1][0]==t){
high=mid-1;
}
else{
printf("%d\n",shu[mid][1]);
return;
}

}

}
}
void chack2(int t,int n){
int low = 1;
int high = n ;
int mid,midnum;
while(low<= high){
mid = (low + high)/2;
midnum = shu[mid][0];
if(midnum<t)
low = mid + 1;
else if(midnum>t)
high = mid - 1;
else{
if(shu[high][0]==t){
printf("%d\n",shu[high][1]);
return;
}
else {
high--;
}
}

}
}
int main(){
int n,m,i,t,type,tag;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&shu[i][0]);
shu[i][1]=i;
}
megre_sort(shu,1,n);
while(m--){
scanf("%d %d",&type,&tag);
if(type==1)
chack(tag,n);
else
chack2(tag,n);
}
return 0;
}

# G Alex and Marvolo won't have a problem. - 3

## Title Description

Alex and Marvolo won't have a problem. So they started chatting:

Alex: I think they are very alert now.

Marvolo: Yes, the hint of the last question has become an expression pack.

Alex: I've decided to wash my hands in a golden basin and turn right. Come up with a difficult and challenging algorithm problem

Marvolo: Oh, roar?

Alex: do you usually watch TV?

Marvolo: I don't think much. I play with my mobile phone.

Alex: Yes, the programs on TV are time limited. You can't see them after this point.

Marvolo: just watch it on your mobile phone.

Alex: No, generally speaking, it's the first broadcast on TV. It's updated on the mobile phone after the TV is played.

Marvolo: so?

Alex: (rummaged through his schoolbag for a while and pulled out a piece of dense paper) here are the program lists of all TV stations, including the start time and end time of each program. How many programs can I watch in a day if I have enough time?

Marvolo: Well, I only updated it at 23:00 PM, so I only watch one a day.

In short, there are n(1 ≤ n ≤ 106) programs broadcast on different radio stations. Given the start time and end time of each program si,ei,(1 ≤ si,ei ≤ 105), assuming unlimited time, how many different programs can you watch at most?

## input

The first line is a positive integer n(1≤n≤106) Next n Rows, 2 positive integers per row si,ei(1≤si<ei≤105) ，Indicates the start and end time of a program.

## output

Output a positive integer per line, indicating the maximum number of programs you can watch

3
1 3
3 4
1 4

2

## analysis

A greedy problem. The earlier the program ends, the better for the viewing plan. Therefore, after sorting the programs, we can calculate how many programs can be watched on time.
The following is my own code for reference only.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#include<math.h>
typedef struct node *nodeptr;
typedef struct node Node;
struct node{
int s;
int e;
};
Node a[1000005];
int cmp(const void *a, const void *b){
Node x = *(Node*)a, y = *(Node*)b;
if(x.e != y.e) return x.e - y.e;
return x.s - y.s;

}
int main(){
int n,count=0,i;
Node last;
last.e=0;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d %d",&a[i].s,&a[i].e);
}
qsort(a+1,n,sizeof(Node),cmp);
for(i=1;i<=n;i++){
if(a[i].s>=last.e){
last=a[i];
count++;
}
}
printf("%d",count);
return 0;
}

# H soul of darkness

## Title Description

After opening the mysterious box, you see a green vine in it. The green vine is about to wither and needs magical rain.

Enter n non negative integers. Each integer represents the height of a square column with a width of 1. Calculate the height map of N columns arranged according to this. How much rain can be received after rain?

Example: suppose the number of n input is [0,1,0,2,1,0,1,3,2,1,2,2,1], which represents the column height diagram shown in the figure below. The total amount of rainwater that can be connected in this diagram is 6.

## input

The first line is an integer n ( 1≤n≤106 )，The meaning is shown above.

Second line n A nonnegative integer a1,a2,...,an( 0≤ai≤106 )，Represents the height of the column.

## output

Output an integer on each line, indicating the total amount of rainwater received.

## sample input

12
0 1 0 2 1 0 1 3 2 1 2 1

6

## analysis

This topic is a little difficult. I didn't make it in the process of getting on the computer, but in the lecture class, some students provided to use the stack to store the concave part until they met the next concave shape, and then back off the stack one by one to calculate the area.

# I nearest point pair

## Title Description

There is a kind of creature on a planet. This kind of creature has a characteristic. They can only walk in two directions parallel to the x-axis and parallel to the y-axis. Now it is known that the population number of this species on the planet is n, and the position of each individual is known, so as to find the minimum distance between them.

As shown below,

Suppose the x-axis is horizontal and the y-axis is vertical. Red, gray and khaki are the routes that creature a can walk to B. of course, this is only part of it. A has countless ways to get to B, as long as it is parallel to the X axis or the Y axis.

## input

The first number is the population n

next n Rows, two floating-point numbers per row x,y，Represent coordinates

## output

A floating-point number representing the minimum distance. Keep 3 decimal places

2
0.00 0.00
1.00 2.00

3.000

## analysis

This topic is a little difficult. It is a classic template topic. I won't repeat it here. Please have a look p613 33.4
The following is my own code for reference only.
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n;
struct node
{
double x, y;
}ar[100050];
int br[100050];
//Used to calculate the distance between two points
double dis(struct node a, struct node b)
{
return fabs(a.x-b.x)+fabs(a.y-b.y);
}
bool cmp1(struct node a, struct node b)
{
return a.x < b.x;
}
bool cmp2(int a, int b)
{
return ar[a].y < ar[b].y;
}
double near_dis(int l, int r)
{
//When there are two or three points left in the recursive distance, then there are only two points left
if(r == l + 1)
return dis(ar[l], ar[r]);
if(l + 2 == r)
return min(dis(ar[l], ar[r]), min(dis(ar[l], ar[l + 1]), dis(ar[l + 1], ar[r])));
//Split and find the results of cases 1 and 2
int mid = (l + r)/2;
double ans = min(near_dis(l, mid), near_dis(mid + 1, r));
//Find the qualified points and sort them by y coordinate
int cnt = 0;
for(int i = l; i <= r; ++i)
{
if(ar[i].x >= ar[mid].x - ans && ar[i].x <= ar[mid].x + ans)
br[++cnt] = i;
}
sort(br + 1, br + cnt + 1, cmp2);
//Find the answer of case 2 and update it continuously
for(int i = 1; i <= cnt; ++i)
{
for(int j = i + 1; j <= cnt; ++j)
{
if(ar[br[j]].y - ar[br[i]].y >= ans)    break;
ans = min(ans, dis(ar[br[i]], ar[br[j]]));
}
}
return ans;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%lf %lf", &ar[i].x, &ar[i].y);
sort(ar + 1, ar + n + 1, cmp1);//Sort by x
printf("%.3f",near_dis(1,n));
return 0;
}