[Week4 homework] A-DDL fear, B-four series, C-TT mysterious gift

A-Fear of DDL

Topic:

ZJM has n assignments, and each assignment has its own DDL. If ZJM does not complete this assignment before DDL, the teacher will deduct all the usual assignments for this assignment.
So ZJM wants to know how to arrange the order of doing homework, in order to deduct as little points as possible.
Please help him!

Input

The input contains T test cases. The first line of input is a single integer T, the number of test cases.
Each test case starts with a positive integer N (1 <= N <= 1000), indicating the number of jobs.
Then two lines. The first line contains N integers, indicating DDL, and the next line contains N integers, indicating points deducted.

Output

For each test case, you should output the smallest total reduction score, one line per test case.

Sample Input

3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4

Sample Output

0
3
5

Hint

There are three sets of samples above.
For the first set of samples, there are three jobs whose DDL are all on the third day. ZJM makes one every day just before the DDL, so there is no penalty and the output is 0.
For the second set of samples, there are three assignments, and their DDLs are the first day, the third day, and the first day. ZJM did the first assignment on the first day and the second assignment the next day, with a total of 3 points deducted and output 3.

Ideas and practices:

Greedy method, because the time to complete each assignment in the question is the same, it is one day, so we only need to consider its value, that is, the score.
Maintain a boolean array b, select a job with the most value from a bunch of DDL, put it into b according to its DDL, if b [DDL] is already true, it means that there is a greater value and its DDL is greater than or equal to the current job The DDL job is put in (the current job cannot be replaced), the current job continues to search forward (can not go back, it may exceed DDL), if it finds a vacancy, it will update b, indicating that there is a job on this day; if the head is found There is no spare day, indicating that this assignment cannot be completed in our greedy algorithm, so he adds his penalties to ans, and it goes through all of them, and the ans value is the answer.

to sum up:

The algorithm looks very simple, but the complexity of the algorithm has not been optimized very well. In the face of very large data, additional optimization is required.

Code:

#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;

const int N = 1010;
bool b[N];
struct DDL{
	int d,p;  //日期 分数 
	bool operator<(const DDL& ddl){
		if(p!=ddl.p) return p>ddl.p;
		return d<ddl.d;
	}
}a[N];

int main(){
	int t; cin>>t;
	while(t--){
		int n, ans = 0; cin>>n;
		memset(b, 0, sizeof(b));
		for(int i = 0; i < n; ++i) cin>>a[i].d;
		for(int i = 0; i < n; ++i) cin>>a[i].p;
		sort(a, a+n);
		for(int i = 0; i < n; ++i){
			int day = a[i].d;
			bool done = 0;
			while(day > 0){  //0不算 
				if(!b[day]){  //放进这一天 
					b[day] = 1;
					done = 1;
					break;
				}
				day--;
			}
			if(!done) ans += a[i].p;  //没有完成 
		}
		cout<<ans<<endl;
	}
	return 0;
} 

B-four series

Topic:

ZJM has four series A, B, C, D, each series has n numbers. ZJM takes a number from each sequence, and he wants to know how many schemes make the sum of the four numbers zero.
When there are multiple identical numbers in a sequence, treat them as different numbers.
Please help him!

Input

The first row: n (representing the number of numbers in the sequence) (1≤n≤4000) In the
next n rows, the i-th row has four numbers, which represent the i-th in the sequence A, B, C, D Digits (numbers not more than 2 to the 28th power)

Output

The number of different combinations is output.

Sample Input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample Output

5

Hint

Sample explanation: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46), (-32, 30, -75, 77 ), (-32, -54, 56, 30).

Ideas and practices:

The complexity of the direct 4-layer cycle is too high, and the 4-layer cycle is split into two 2-layer cycles.
Because when there are multiple same numbers in a sequence, treat them as different numbers, you can combine the first 2 arrays into 1 array, the last 2 arrays into 1 array, for the last 1 array For each element of, find the opposite number in the first array, and add all of them to get the answer.
In order to further reduce the complexity, the problem of finding the number is converted into finding the position of the first and last occurrence of the opposite number in the array (the difference between the front and back positions), using the find_index function to find the binary search, if the function returns not -1 ( -1 means the number is not found), update ans. After going through it all, ans is the answer.

to sum up:

For a question. You can find ways to achieve it, and then look for further optimization methods.

Code:

#include <iostream>
#include <algorithm>
using namespace std;

const int N = 4010;
int a[N], b[N], c[N], d[N];
int ab[N*N];

int find_index(int num, int len, bool last){
//找num在ab[0,len)数组中第一次或最后一次last出现的位置 
	int l = 0, r = len-1, ans = -1;  //找不到返回-1 
	while(l <= r){
		int mid = (l + r) >> 1;
		if(ab[mid] == num){
			ans = mid;
			if(!last) r = mid - 1;
			else l = mid + 1;
		}
		else if(ab[mid] < num) l = mid + 1;
		else r = mid - 1;
	}
	return ans;
}

int main(){
	int n, ans = 0; cin>>n;
	for(int i = 0; i < n; ++i)
		cin>>a[i]>>b[i]>>c[i]>>d[i];
		
	for(int i = 0; i < n; ++i)
		for(int j = 0; j < n; ++j)
			ab[i*n+j] = a[i] + b[j];
			
	sort(ab, ab+n*n);
	
	for(int i = 0; i < n; ++i){
		for(int j = 0; j < n; ++j){
			int last = find_index(-(c[i]+d[j]), n*n, 1);
			if(last != -1) ans += last-find_index(-(c[i]+d[j]), n*n, 0)+1;
		}
	}
	cout<<ans<<endl;
	return 0;
}

C-TT's mysterious gift

Topic:

TT is a serious cat lover who indulges in the cat channel on station B every day.
One day, TT's friend ZJM decided to give TT a problem. If TT can solve this problem, ZJM will buy a cute cat and give it to TT.
The task content is, given an N number array cat [i], and use this array to generate a new array ans [i]. The new array is defined as for any i, j and i! = J, all have ans [] = abs (cat [i]-cat [j]), 1 <= i <j <= N. Try to find the median of this new array. The median is the number corresponding to the (len + 1) / 2 position after sorting, and '/' is rounded down.
TT wants to get that cute cat very much, can you help him?

Input

Multiple sets of input, each time enter an N, which means that there are N numbers, and then enter a sequence cat of length N, cat [i] <= 1e9, 3 <= n <= 1e5

Output

Output the median of the new array ans

Sample Input

4
1 3 2 4
3
1 10 2

Sample Output

1
8

Ideas and practices:

If the ans [] is obtained according to the easiest way to think of, the median is naturally available, but the complexity of this is too high, and the relationship between the median and the rank is optimized.
The specific method is to first find the limit of the possible values ​​of the elements in ans [], the minimum is 0, and the maximum is the number with the largest difference (max-min) in the cat [] array. Due to the relationship between rank and median, you can Find the median in such a range.
In order to find the rank of any number P, we need to calculate | cat [j]-cat [i] | ]-derived from cat [0]. Next, calculate the rank of P and convert it to any i (0 <= i <n-1), and find the sum of the number of cat [j] <= P + cat [i]. You can still find the first and last occurrence of such cat [j] by dichotomy (cat has been sorted and can be dichotomized) to calculate the number of cat [j] that meet the conditions.
Finally, the P value is updated by comparing the number sum (namely the rank of P) with the median rank. The P we want is the first P value whose rank is not less than the median rank, because the rank of P before it is low, and the rank of P behind it is greater than or equal to the median rank. , The first P not less than the median rank is naturally the median.

to sum up:

The idea is very clear, and the dichotomy is not difficult to write. The reason why I ca n’t pass it is because I forgot how to calculate the number of combinations during the process of writing the code. One, but RE. Later I learned that it was actually very simple, n (n-1) / 2 can be calculated, so I got the result but it timed out, and changed cin to scanf before AC

Code:

#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 100050;
int cat[N], n;

int find_index(int start, int P){
	int l = start+1, r = n-1, ans = -1;
	while(l <= r){
		int mid = (l + r) >> 1;
		if(cat[mid] <= cat[start]+P){
			ans = mid;
			l = mid + 1;
		}
		else r = mid - 1;
	}
	return ans;
} 

int G(int P){
	int ans = 0;
	for(int i = 0; i < n-1; ++i){
		int num = find_index(i, P);
		if(num != -1) ans += (num-i);
	}
	return ans;  //返回名次 
}

int main(){
	while(~scanf("%d", &n)){
		for(int i = 0; i < n; ++i) scanf("%d", &cat[i]);
		sort(cat, cat+n);
		int ans = -1, l = 0, r = cat[n-1]-cat[0], num = n*(n-1)/2;
		while(l <= r){
			int mid = (l + r) >> 1;
//			cout<<"l="<<l<<" r="<<r<<" mid="<<mid<<" G="<<G(mid)<<endl;
			if(G(mid)<(num+1)/2) l = mid + 1;
			else{
				ans = mid;
				r = mid - 1;
			}
		}
		printf("%d\n", ans);
	}
	return 0;
}
Published 10 original articles · Likes0 · Visits 231

Guess you like

Origin blog.csdn.net/weixin_44898140/article/details/104929064