프로그램 설계 생각 Week4- 작업

상세 프로그래밍 Week4- 작업

A-DDL 공포

기술

ZJM이있다 N 작업, 각 작업은 자신의 DDL을 가지고 ZJM는 DDL 전에 일을하지 않을 경우, 다음 교사가 모든 일반적인 점을이 작업을 공제합니다. 그래서 ZJM은 가능한 한 조금 덜 포인트 버클 숙제의 순서를 정렬하는 방법을 알고 싶어요.
T 테스트 입력. 각 작업 시험 량 (1 <= N <= 1000 N을 갖는다 ), 및 분수 형 작업 입력 DDL 공제된다.
적어도 버클 점수에서 각 테스트 케이스의 출력.

견본

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

output:
0
3
5

생각

첫째, 각 작업의 사용자 정의 구조에 대한 DDL 및 차감 포인트가 포함되어 있습니다. 각 테스트 케이스에 대한 N 작업 매일 앞에 열거 위로부터 그 배열의 첫 번째 요소에서 시작하여 각 태스크를 들어, 하루 스케쥴을 상기 DDL 감소, 그리고 제 순서는 모든 상기 X 일 열거 DDL = X는 최대 힙 작업이 완료 열거 1 일까지 추가 또는 차감 포인트 (점수 최대 힙 정렬 각 작업에 따라 버클)을 첨가 한 후, 가장 큰 요소 스택에서 스택의 상단에서,이 날 주선 일, 최대 힙 후 비어 있지 않은 경우 이러한 작업은 버클 점수를 추가, 연체입니다. 최종 출력 총 점수 버클

요약

문제 해결의 기본 아이디어는 날이 DDL을 마련하기 위해 욕심 알고리즘, 욕심 기준은, 종료일로부터 1 일 앞으로입니다> = 적은 점을 떠나는 일 일 버클 부분의 가장 큰 임무는, 공제.
의 후면에서 유일한 일 X = X DDL, 최대 스택 DDL 작업이 같거나 X 큰 최초의 X 일에 대한 작업을 보장하기에 추가 열거, DDL은 힙에서하지 잘못 작은 작업 리드를 수행 작업 시간 제한.

코드

#include <iostream>
#include <algorithm>
#include<cstdio>
#include<cstdlib>
#include <vector>
#include<queue>
using namespace std;
int T;
struct task {
	int DDL, s;
	//bool operator()(const task &t) {
	//	return s  t.s;
	//}
}P[1100];
struct cmp {
	bool operator()(task a, task b) {
		return a.s < b.s;
	}
};
bool compare(const task &a, const task &b) {
	return a.DDL > b.DDL;
}

int main()
{
	cin.sync_with_stdio(false);
	cin >> T;
	while (T--) {
		int N;
		cin >> N;
		//memset(P, 0, sizeof(task));
		//memset(s, 0, sizeof(int));
		int score = 0;

		for (int i = 0; i < N; i++)
			cin >> P[i].DDL;
		for (int i = 0; i < N; i++)
			cin >> P[i].s;
		sort(P, P + N,compare);
		int index = 0;
		priority_queue<task,vector<task>,cmp > Q;
		for (int t = 1010; t >= 1; t--) {
			//if (index >= N)break;
			for (; index <N; index++) {
				
				if (P[index].DDL == t) { Q.push(P[index]); }
				else if (P[index].DDL < t)break;
			}
			if (!Q.empty()) {
				task temp = Q.top();
				
				Q.pop();
				//if (temp.DDL < t) { score += temp.s;  }

			}

		}
		while (!Q.empty()) {
			task temp = Q.top();
			Q.pop();
			score += temp.s;
			/*cout << temp.s << endl;*/
		}

		cout << score << endl;

	}

}


B- 네 개의 열

기술

ZJM 각 열에는 N 자리수의 숫자를 가지며, 네 개의 열 A, B, C, D를 갖는다. ZJM 각각의 열 번호에서 가져온 숫자, 그는 같은 4 0의 수를 그 프로그램의 몇 가지를 알고 싶습니다. 컬럼의 숫자는 숫자 같은 복수가있는 경우, 다른 번호로 처리합니다.
네 개의 요소, 다른 출력 조합의 수의 열의 수 N.

견본

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

output:
5

생각

먼저, 각각 번호 B의 열거는, A + B는 각 컬럼의 숫자의 오름차순으로 열 수를 첨가 한 후, 그 반대 번호 검색에, C + D의 각각에 대해, C 및 D의 각각의 번호를 열거 열 번호에 나타나는 숫자, 즉 정렬 순서 찾을 성과 - 필요성은 첫 번째와 마지막의 두 수의 합을 찾기 위해 각각 이진 검색을 사용하는 (C + D)를 첨가 빼기 최종 합계는 다른 조합의 수이다.

요약

(C - 일 개 측면에서, 네 개의 숫자 0, (A)에 대응하고는 + B =의 합, 복잡성을 감소하고, AB는 각각 CD를 열거하며, 각 열거 번호 ABCD는 복잡도는 4 승에 도달 할 + D). 반면에,이 질문의 핵심은 이진 검색의 사용, 복잡성이 logn로 감소된다 첫 번째 항목의 번호와 주문 순서의 마지막 발생의 위치를 ​​찾는 것입니다.

코드

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
int n;
int A[4010];
int B[4010];
int C[4010];
int D[4010];
vector<int> AB;
int sum = 0;

int find1(int x) {
	int l = 0, r = AB.size() - 1, ans = -1;
	while (l <= r) {
		int mid = l + r >> 1;
		if (AB[mid] == x) {
			ans = mid;
			r = mid - 1;
		}
		else if (AB[mid] > x)r = mid - 1;
		else l = mid + 1;
	}
	return ans;
}

int find2(int x) {
	int l = 0, r = AB.size() - 1, ans = -1;
	while (l <= r) {
		int mid=(l + r) >> 1;
		if (AB[mid] == x) {
			ans = mid;
			l = mid + 1;
		}
		else if (AB[mid] > x)r = mid - 1;
		else l = mid + 1;
	}
	return ans;
}

int main()
{
	cin.sync_with_stdio(false);
	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.push_back(A[i] + B[j]);
		}
	sort(AB.begin(), AB.end());
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++) {
			int temp = -(C[i] + D[j]);
			int first = find1(temp);
			int last = find2(temp);

			if (first != -1 && last != -1) { sum += last - first + 1; }
			

		}

	cout << sum << endl;

}


C-TT의 신비한 선물

기술

지정된 배열 고양이 [I] 수 N과는 어레이 [i]는 새로운 어레이 ANS를 생성한다. 그것은 모든 I, J에 대한 새로운 배열로 정의하고 난 J =이되고있다 ANS [] = ABS (CAT [I] - 고양이 [J])! 1 <= I <J <= N. 이러한 새로운 배열. 평균 결정은, 그 중간의 위치 번호에 대응하는 정렬 (+ 1 렌) / 2이고, '/'라운딩이다.

입력의 복수 세트, 길이 N 고양이, 고양이 [I]의 시퀀스를 입력 한 후 입력 한 각각 N, N을 표현할 수 <= 1E9, 3 <= N <= 1E5. 출력 새로운 배열 중간 ans와

견본

input:
4
1 3 2 4
3
1 10 2

output:
1
8

생각

원래 배열 계산 범위 이진 P 않음을 발견이 범위에서는, 우선 새로운 배열 요소 값으로 정렬되어, P는 P P의 각 비트 수는 새 순위 시퀀스를 계산한다.
원래의 열 개수가 정렬되어 있기 때문에, 절대 값, Xj에는 <= 사이 + P를 수득 이동 여기서 산출 된 조건을 만족하는 인덱스 J의 열거 수가 먼저 동일한보다 큰 경우 찾는 이진 검색을 사용하는 것도 가능하다 그때 계산 첨자 수 사이 + P 포지션 수와, 숫자 즉 자격 튜플 조건을 만족하고, 순위의 평균 수를 비교 모든 J 최종 합계는, 순위가 낮은 중앙값보다가 중간 오른쪽이다 중앙값은 좌측 중간 순위보다 크면 두 값이 동일한 경우 측은 새로운 배열 요소에 대응 업데이트 범위 조회 값하고, P는 중간 값이다.

각각 1,3,2,4- 수 4 가정
- 절반 답변으로 다음과 같습니다 :
그림 삽입 설명 여기

요약

P 진 않음 순위 P + I 개의 열거 계산
0부터 시작 후 저장 요소가 보낸, 중앙값이 분류 코드 (+ 1 렌)이다 / 2-1 위치 번호에 대응. 주어진 키에 대한이 질문은 중간이 아닌 숫자 대신 [0, cat_max-cat_min]의 새로운 시리즈에 속해 있어야 요소의 계산 된 평균에 대한 열의 새로운 수를 결정하는 방법이다. 어떻게 상대적으로 긴에서 생각하는 튜플의 수를 계산합니다.

코드

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

int N;
int cat[100010];


int find(int x) {
	int l = 0, r = N - 1, ans = N;
	while (l <= r) {
		int mid = l + r >> 1;
		if (cat[mid] >= x) {
			ans = mid;
			r = mid - 1;
		}
		else if (cat[mid] > x)r = mid - 1;
		else l = mid + 1;
	}
	return ans;
}


int main()
{
	while (scanf("%d",&N)!=EOF) {
		for (int i = 0; i < N; i++)
			 scanf("%d",&cat[i]);
		sort(cat, cat + N);

		int min = 0, max = cat[N - 1] - cat[0],P;
		int index = (N*(N - 1) / 2 + 1) / 2-1;
		//二分答案
		while (min < max) {
			P = (min + max) >> 1;
			int pos = 0;		
			for (int i = 0; i < N; i++)
				pos += N - find(cat[i] + P);		//枚举i,计算满足条件的j的个数
			if (pos >= N*(N - 1) / 2 - index)min = P + 1;
			else max = P;
		}
		printf("%d\n", min - 1);
	}
}


게시 21 개 원래 기사 · 원 찬양 5 · 조회수 784

추천

출처blog.csdn.net/weixin_44578615/article/details/104846940